Iwasang mailantad ang secrets sa AI agents
Maaaring ma-leak ng AI agent ang API key sa isang tool call. Gumamit ng scoped, short-lived token sa credential gateway, hindi ng aktuwal na key.
Ano ang ibig sabihin ng pag-iwas na mailantad ang mga lihim sa mga AI agent
Ang AI agent ay isang karaniwang Linux process na nagpapatakbo ng mga command. Nababasa ng code na pinapatakbo nito ang bawat environment variable na hawak ng process. Kaya ang API key sa environment ng agent ay key na maaaring ipadala ng agent sa anumang host na maaabot nito. Ang pag-iwas na mailantad ang mga lihim sa agent ay nangangahulugang bibigyan ito ng handle sa halip na key: isang short-lived at scoped token, o isang placeholder na pinapalitan ng ibang component ng aktuwal na value sa network boundary.
Hindi ito tungkol sa modelong nagiging hostile. Mas simple ang mekanismo. Nagbabasa ang agent ng web page, README, o issue comment na naglalaman ng mga instruction. Sinusunod nito ang mga ito dahil para sa language model, walang pagkakaiba ang text na isinulat mo at ang text na kinuha nito. Iyan ang prompt injection. Kapag nangyari ito, ang pinsala ay nalilimitahan ng isang bagay lamang: kung ano ang mababasa ng process. Kung hindi ka pa nagtatakda ng boundary, ipinapaliwanag ng ligtas na pagpapatakbo ng coding agent sa server ang mga antas ng isolation na pinagbabatayan ng guide na ito.
Ang threat model sa payak na mga termino
Patakbuhin ito bilang user na pinapatakbo ng iyong agent.
tr '\0' '\n' < /proc/self/environ | grep -iE 'key|token|secret|password'Ang bawat linyang pini-print nito ay isang HTTP request lamang ang layo mula sa server ng isang hindi kilalang tao. Tingnan ngayon kung ano ang nasa disk na malapit sa agent.
grep -rIl --exclude-dir=.git -e 'API_KEY' -e 'SECRET' ~/projects
find ~ -maxdepth 3 -name '.env' -o -name 'credentials' -o -name '*.pem'Ang agent na may shell ay hindi nangangailangan ng sopistikadong exploit para mailabas ang data na iyon. Apat na karaniwang paraan ang sapat, at lahat ng ito ay mukhang normal na gawain sa log:
- Isang outbound na
curlofetchpapunta sa anumang host, na nasa query string ang value. - Isang
git commitatgit pushpapunta sa repository na maaaring sulatan ng agent. - Isang package install script, na nagpapatakbo ng arbitrary code bilang user ng agent.
- Isang DNS lookup ng hostname na naglalaman ng value. Nakakalabas ito kahit naka-block ang HTTP egress.
Hindi ito malulutas sa simpleng pag-review. Ang solusyon ay tiyaking walang mahalagang data na maaabot.
Ang isang secret sa working tree ay secret sa context window
Nagbabasa ng mga file ang isang agent. Babasahin ang .env file sa repository na ginagamit nito, at kapag nabasa na ito, nasa context window na ito. Ibig sabihin, nasa transcript ito, nasa anumang log na pinapanatili mo, at nasa anumang susunod na isusulat ng agent.
Dati, habang nasa tree na ginagamit ng agent ang key:
cd ~/projects/billing
cat .env
# STRIPE_SECRET_KEY=sk_live_...
# DATABASE_URL=postgres://app:hunter2@db.internal:5432/billingNgayon, matapos ilipat ang file sa lugar na hindi na maaabot ng agent:
sudo install -d -m 750 -o root -g agent-review /etc/agent-review
sudo install -m 640 -o root -g agent-review ~/projects/billing/.env /etc/agent-review/billing.env
rm ~/projects/billing/.envHindi na mabubuksan ng user ng agent ang file, dahil wala na ito sa working tree. Ang mga deny rule sa sariling config ng agent ay pangalawang layer lamang, hindi ang unang layer. Binabasa ni Claude Code ang mga permission rule mula sa .claude/settings.json sa project:
{
"permissions": {
"deny": ["Read(./.env)", "Read(./secrets/**)", "Read(./**/*.pem)"]
}
}Pinipigilan nito ang tapat na pagkakamali ng agent na magbukas ng file habang nag-e-explore. Hindi nito pinipigilan ang injected instruction na patakbuhin ang base64 .env, dahil shell command ito at hindi pagbasa ng file. Ituring ang config bilang guardrail at ang filesystem permission bilang harang. Pareho rin ang paghahati sa loob ng mga container: saklaw ng mga env file at secret sa Docker Compose ang bersyon ng problemang ito na isang layer sa ibaba.
Bigyan ang bawat agent ng sarili nitong unprivileged user
Kung tumatakbo ang agent bilang ikaw, mamanahin nito ang iyong SSH keys, cloud credentials, at shell history. Isang command lang ang kailangan para sa hiwalay na user, at aalisin nito ang lahat ng iyon.
sudo adduser --disabled-password --gecos "" agent-review
sudo chmod 700 /home/agent-review
sudo -u agent-review cat ~/.ssh/id_ed25519Dapat mag-fail ang huling linya gamit ang cat: /home/you/.ssh/id_ed25519: Permission denied. Kung nag-print ito ng key, group o world readable ang iyong home directory, at inaayos ito ng chmod 700 ~. Huwag idagdag ang agent user sa sudo, at huwag itong bigyan ng NOPASSWD rule na mas malawak kaysa sa isang command na talagang kailangan nito. Tinalakay sa Mga user na may least privilege sa isang VPS ang mga detalye tungkol sa group at sudoers.
Mahalaga ring magdagdag ng isa pang boundary sa isang cloud VPS. Sumasagot ang instance metadata service sa isang fixed link-local address, at madalas itong nagbibigay ng role credentials sa anumang humihingi nito.
sudo iptables -A OUTPUT -m owner --uid-owner agent-review -d 169.254.169.254 -j REJECTSuriin ito mula sa panig ng agent. Dapat walang i-print ang sudo -u agent-review curl -s --max-time 3 http://169.254.169.254/ at dapat itong mag-exit na non-zero, dahil nire-reject ang packet bago ito lumabas sa box.
I-inject ang credential sa boundary
Ang pattern na talagang lumulutas dito ay credential injection. Hindi kailanman hinahawakan ng agent ang aktuwal na key. Ipinapadala nito ang request sa isang lokal na gateway, at pinapalitan ng gateway ang placeholder ng aktuwal na secret habang ipinapadala ang request. Nasa storage ng gateway ang secret, sa ibang process, at pagmamay-ari ito ng ibang user.
Ang OneCLI ay isang open source na implementasyon nito, lisensyado sa ilalim ng Apache-2.0, at tumatakbo ito bilang container sa tabi ng agent. Noong July 2026, idinodokumento ng project ang setup na ito:
git clone https://github.com/onecli/onecli.git
cd onecli
docker compose -f docker/docker-compose.yml up -d --waitNakikinig ang dashboard sa port 10254, at ang gateway naman sa 10255. Isang beses mong ise-save ang aktuwal na credential, pagkatapos ay bibigyan mo ang bawat agent ng placeholder value kapalit ng key, kasama ang sarili nitong scoped access token na ipinapadala nito sa isang Proxy-Authorization header. Tinutukoy ng gateway ang outbound request batay sa host at path, dine-decrypt ang katugmang credential, at ipinapalit ito. Walang hawak ang environment ng agent na halagang sulit nakawin.
Hindi encryption ang pangunahing pakinabang dito. Ang mahalaga ay nagiging log query ang tanong na “ano ang ginamit ng agent na ito, at kailan?” Binabasa mo ang isang audit trail sa halip na manghula kung alin sa anim na environment ang may kopya ng key.
Ibigay ang secret sa process, hindi sa environment
Kung patatakbuhin mo ang agent sa ilalim ng systemd, hindi mo na kailangan ng environment variables. Inilalagay ng LoadCredential= ang secret sa isang pribadong directory na mababasa lamang ng serbisyong iyon. Lumalabas ito bilang %d sa unit file at bilang $CREDENTIALS_DIRECTORY sa loob ng process. Hindi kailanman lumalabas ang value sa /proc/<pid>/environ, kaya hindi ito maipapakita ng ps eww. Nawawala rin ang directory kapag huminto ang service.
I-encrypt muna ang credential para sa machine. Mula sa systemd documentation ang mga command na ito. Gumagana ang mga ito sa systemd 250 o mas bago, kabilang ang Ubuntu 24.04 at Debian 13:
echo -n 'sk-example-value' > /tmp/plain.txt
sudo systemd-creds encrypt --name=api_key /tmp/plain.txt /etc/credstore/api_key.cred
shred -u /tmp/plain.txt
sudo systemd-run -P --wait -p LoadCredentialEncrypted=api_key:/etc/credstore/api_key.cred \
systemd-creds cat api_keyIpinapakita ng huling command ang sk-example-value. Pinatutunayan nito na nade-decrypt ang encrypted file sa host na ito. Pagkatapos, i-reference ito mula sa unit:
[Service]
User=agent-review
LoadCredentialEncrypted=api_key:/etc/credstore/api_key.cred
Environment=AGENT_KEY_FILE=%d/api_key
ExecStart=/usr/local/bin/agent-workerBinubuksan ng agent code ang file sa $AGENT_KEY_FILE kapag kailangan nito ang value. Panandalian lamang ang pagbasa ng file. Nananatili ang environment variable sa buong buhay ng process, kasama sa bawat child na sini-spawn nito.
Mas mainam ang mga token na maikli ang bisa kaysa sa mga key na matagal ang bisa
May bisa pa rin ang isang key na hindi kailanman nag-e-expire kapag lumitaw ito, makalipas ang ilang buwan, sa isang log o transcript. Kapag nagbibigay ang service ng session token, gamitin ang session token at itakda ang pinakamaikling lifetime na pinapayagan ng gawain.
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/agent-readonly \
--role-session-name agent-review \
--duration-seconds 900Ang 15 minuto ang minimum na tinatanggap ng AWS STS (security token service), at karaniwan itong sapat para sa isang agent task. Para sa GitHub, gumawa ng sariling gh login para sa agent user, na may fine-grained token na naka-scope sa iisang repository lang na pinagtatrabahuhan nito. Sa ganitong paraan, ang gh auth token sa loob ng session na iyon ay nagbabalik ng access na walang ibang kayang galawin. Unahin ang pag-scope ayon sa resource, saka ayon sa oras.
I-verify, pagkatapos ay patuloy na mag-verify
May tatlong check na dapat patakbuhin pagkatapos ng anumang pagbabago sa setup ng isang agent. Patakbuhin ang mga ito bilang user ng agent, hindi bilang sarili mong user.
sudo -u agent-review env | grep -iE 'key|token|secret'
sudo -u agent-review ls -la /home/you/ 2>&1 | head -3
sudo -u agent-review curl -s -o /dev/null -w '%{http_code}\n' --max-time 5 https://api.github.com/userAng una ay dapat walang i-print. Dapat i-print ng ikalawa ang ls: cannot open directory '/home/you/': Permission denied. Ipinapakita ng ikatlo kung anong identity ang ipinapakita ng network path ng agent. Ito ang tanong na sinasagot ng gateway pattern: ang 401 ay nangangahulugang walang sariling GitHub credential ang agent, habang ang 200 ay nangangahulugang mayroon itong credential. Dapat mong malaman kung aling token iyon. Kung nagpapatakbo ka ng mga agent nang walang supervision, saklaw ng pagkontrol sa mga gastos ng AI agent sa isang VPS ang mga limitasyon sa budget na kaugnay ng mga limitasyong ito sa access.
FAQ
Maaari ko bang basta pagkatiwalaan ang model na hindi i-leak ang mga key ko?
Hindi, dahil hindi ang model ang attacker sa threat model na ito. Nagbabasa ang agent ng text mula sa mga web page, repository, at issue tracker, at maaaring may mga instruction ang text na iyon. Walang maaasahang paraan ang model para matukoy kung alin ang instructions mo at alin ang text na kinuha nito. Nabibigo ang anumang control na nakadepende sa tamang pagpili ng model sa unang pagkakataong kapani-paniwala ang injected instruction. Kaya dapat nasa operating system o network ang control.
Talaga bang masama ang environment variables para sa agent secrets?
Masama ang mga ito sa isang partikular na paraan: namamana ang mga ito. Nakakakuha ng kopya ang bawat child process na bina-launch ng agent, kabilang ang build script, test runner, at anumang package install hook. Mababasa rin ang mga variable sa pamamagitan ng /proc/<pid>/environ ng parehong user. Kaya mababasa ng anumang pinapatakbo ng agent ang mga ito nang hindi kailangang ipasa ng agent. Nililimitahan ng file na binabasa sa oras ng paggamit, gamit ang LoadCredential= o gateway, ang exposure sa mismong oras na iyon.
Nalulutas ba nito nang mag-isa ang paglalagay ng secrets sa vault?
Bahagya lamang. Inaayos ng vault ang storage. Hindi nito inaayos ang huling hakbang, kung saan may kumukuha ng secret mula sa vault at ipinapasa ito sa agent bilang environment variable. Ibinabalik ka nito sa dating sitwasyon. Ang mahalaga ay kung sino ang nagsasagawa ng substitution. Kung ang agent ang kumukuha ng secret, nasa agent ang secret. Kung gateway o init system ang nagsasagawa ng substitution sa labas ng process ng agent, hindi kailanman hawak ng agent ang secret.
Paano ko malalaman kung may na-leak na ang agent?
Karaniwan, hindi mo malalaman pagkatapos mangyari, at ito ang dahilan kung bakit kailangan ang gateway. Kung wala nito, nakakalat ang ebidensya sa shell history, transcript ng agent, at outbound connection logs na malamang ay hindi mo nire-record. Kung may credential gateway, ang bawat paggamit ng credential ay isang linya na may identity ng agent at timestamp. Kung pinaghihinalaan mong may leak, i-rotate muna ang key at saka magsiyasat. Mura ang rotation, ngunit hindi mura ang katiyakan.
Ano ang minimum na dapat kong gawin ngayon?
Ilipat ang bawat .env file sa labas ng mga directory na ginagamit ng iyong mga agent, at gumawa ng isang unprivileged user para sa bawat agent. Tumatagal nang humigit-kumulang sampung minuto ang dalawang pagbabagong ito at sinasarhan ang pinakakaraniwang path: ang pagbasa ng agent sa credential file na walang dahilan para nasa tabi ng code. Ang gateway at short-lived token ang susunod na hakbang, hindi ang unang hakbang. Pareho ang panimulang puntong ito para sa anumang agent runtime, kabilang ang ligtas na pagpapatakbo ng autonomous agent sa isang VPS.