SSD Nodes Learn Hosting plans →
Mga Gabay Matt ConnorNi Matt Connor · Na-update 2026-08-31

Huwag Ilagay ang API Keys sa AI Agents

Maaaring ma-leak ang API key sa isang tool call. Gumamit ng scoped, short-lived token sa credential gateway, hindi ng tunay na key sa agent.

Ano ang ibig sabihin ng pag-iwas na ilagay ang secrets sa AI agents

Ang AI agent ay isang normal na 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 isang key na maaaring ipadala ng agent sa anumang host na maaabot nito. Ang pag-iwas na ilagay ang secrets sa agent ay nangangahulugang pagbibigay rito 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 model na naging hostile. Mas simple ang mekanismo. Nagbabasa ang agent ng web page, README, o issue comment na may instructions, at sinusunod nito ang mga iyon. Para sa language model, walang pagkakaiba ang text na isinulat mo at text na kinuha nito. Ito ang prompt injection. Kapag nangyari ito, nakadepende ang lawak ng damage sa iisang bagay: kung ano ang nababasa ng process. Kung wala ka pang boundary, tinatalakay sa ligtas na pagpapatakbo ng coding agent sa server ang mga isolation rung na pinagsasaligan ng guide na ito.

Ang threat model sa payak na paliwanag

Patakbuhin ito bilang user na ginagamit ng iyong agent.

tr '\0' '\n' < /proc/self/environ | grep -iE 'key|token|secret|password'

Ang bawat linyang inilalabas nito ay isang HTTP request lang 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'

Hindi kailangan ng agent na may shell 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 curl o fetch papunta sa kahit anong host, kung saan nasa query string ang value.
  • Isang git commit at git push papunta 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 pa rin ito kahit naka-block ang HTTP egress.

Hindi ito malulutas sa pamamagitan lamang ng pagsusuri. Ang solusyon ay tiyaking walang mahalagang data na maaabot nito.

Ang isang secret sa working tree ay secret sa context window

Ang agent ay nagbabasa ng mga file. Babasahin ang .env file sa repository na pinagtatrabahuhan nito. Kapag nabasa na ito, nasa context window na ito. Ibig sabihin, nasa transcript ito, sa anumang log na iniingatan mo, at sa anumang susunod na isusulat ng agent.

Dati, habang nasa working tree ng agent ang key:

cd ~/projects/billing
cat .env
# STRIPE_SECRET_KEY=sk_live_...
# DATABASE_URL=postgres://app:hunter2@db.internal:5432/billing

Pagkatapos ilipat ang file sa lugar na hindi nito maaabot:

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/.env

Hindi na mabubuksan ng user ng agent ang file dahil wala na ito sa working tree. Ang deny rules sa sariling config ng agent ay pangalawang layer lamang, hindi unang depensa. Binabasa ng Claude Code ang permission rules mula sa .claude/settings.json sa project:

{
  "permissions": {
    "deny": ["Read(./.env)", "Read(./secrets/**)", "Read(./**/*.pem)"]
  }
}

Pinipigilan nito ang tapat na pagkakamali kung saan bubuksan ng agent ang isang file habang nag-e-explore. Hindi nito pinipigilan ang injected instruction na magpatakbo ng base64 .env dahil shell command ito, hindi file read. Depende sa permission mode ng session kung hihingi muna ng pahintulot bago patakbuhin ang command. Dahil magiging default ng Claude Code ang auto mode sa August 2026, mas marami sa mga command na ito ang awtomatikong tatakbo sa server na hindi mo mino-monitor. Pareho ang limitasyong ito sa anumang humuhubog sa mga gawi ng agent sa halip na sa permissions nito: pinananatili ng isang skill ang agent sa pinakamaliit na pagbabagong gumagana at pinipigilan ang run na mapunta sa mga file na wala itong dahilan para buksan, pero payo pa rin ito na maaaring mabago ng pakikipag-usap sa model. Ituring ang config bilang guardrail at ang filesystem permission bilang pader. Pareho ring umiiral ang paghahating ito sa loob ng containers: tinutukoy ng env files at secrets sa Docker Compose ang bersyon ng problemang ito na nasa 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 maaalis 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_ed25519

Dapat mag-fail ang huling linya gamit ang cat: /home/you/.ssh/id_ed25519: Permission denied. Kung key ang ipinakita nito, group-readable o world-readable ang iyong home directory, at inaayos ito ng chmod 700 ~. Huwag idagdag ang agent user sa sudo, at huwag bigyan ito ng NOPASSWD rule na mas malawak kaysa sa iisang command na talagang kailangan nito. Ipinapaliwanag sa Mga least privilege user sa VPS ang detalye ng groups at sudoers. Panatilihin ang paghihiwalay na ito kapag nagpapatakbo ka na ng higit sa isang session sa server, dahil maaaring direktang magpadala ng text ang isang Claude Code session sa isa pa, at maaaring tumawid sa channel na iyon sa isang mensahe ang anumang hawak ng unang session.

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 humihiling.

sudo iptables -A OUTPUT -m owner --uid-owner agent-review -d 169.254.169.254 -j REJECT

Suriin 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 server.

I-inject ang credential sa boundary

Ang pattern na talagang lumulutas dito ay credential injection. Hindi kailanman hinahawakan ng agent ang tunay na key. Ipinapadala nito ang request sa isang local gateway, at pinapalitan ng gateway ang placeholder ng tunay na secret habang ipinapadala ito palabas. Nasa storage ng gateway ang secret, nasa ibang process, at pagmamay-ari ng ibang user.

Ang OneCLI ay isang open source na implementasyon nito. May Apache-2.0 license ito at tumatakbo bilang container katabi ng agent. Noong July 2026, ganito ang setup na nakadokumento sa project:

git clone https://github.com/onecli/onecli.git
cd onecli
docker compose -f docker/docker-compose.yml up -d --wait

Nakikinig ang dashboard sa port 10254, at ang gateway naman sa 10255. Minsan mong ini-store ang tunay na credential. Pagkatapos, binibigyan mo ang bawat agent ng placeholder value kapalit ng key, pati ng sarili nitong scoped access token na ipinapadala nito sa isang Proxy-Authorization header. Tinutukoy ng gateway ang outbound request batay sa host at path, dini-decrypt ang katugmang credential, at pinapalitan ang placeholder nito. Walang mahalagang secret na naka-store sa environment ng agent na maaaring manakaw.

Hindi encryption ang pangunahing pakinabang dito. Ang mahalaga ay nagiging log query ang tanong na “ano ang ginamit ng agent na ito, at kailan?” Isang audit trail lang ang babasahin mo, sa halip na hulaan kung alin sa anim na environment ang may kopya ng key.

Ibigay ang secret sa process, hindi sa environment

Kung pinapatakbo mo ang agent sa ilalim ng systemd, hindi mo na kailangan ng environment variables. Inilalagay ng LoadCredential= ang secret sa isang private directory na tanging ang service na iyon ang makakabasa, inilalantad ito bilang %d sa unit file at bilang $CREDENTIALS_DIRECTORY sa loob ng process. Hindi kailanman lumilitaw ang value sa /proc/<pid>/environ, kaya hindi ito maipapakita ng ps eww, at nawawala ang directory kapag huminto ang service.

I-encrypt muna ang credential para sa machine. Mula sa systemd documentation ang mga command na ito at 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_key

Ipinapakita ng huling command ang sk-example-value. Pinatutunayan nitong 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-worker

Binubuksan ng iyong agent code ang file sa $AGENT_KEY_FILE kapag kailangan nito ang value. Panandalian lamang ang file read. Nanatili ang environment variable habang tumatakbo ang process, pati sa bawat child process na ginagawa nito.

Piliin ang mga token na maikli ang lifetime kaysa sa mga key na matagal bago mag-expire

Valid pa rin ang key na hindi kailanman nag-e-expire kapag lumitaw ito makalipas ang ilang buwan sa isang log o transcript. Kung nag-aalok ang serbisyo ng session token, iyon ang gamitin at itakda ang pinakamaikling lifetime na pinapahintulutan ng gawain.

aws sts assume-role \
  --role-arn arn:aws:iam::123456789012:role/agent-readonly \
  --role-session-name agent-review \
  --duration-seconds 900

Labinlimang minuto ang minimum na tinatanggap ng AWS STS (security token service), at karaniwan itong sapat para sa isang agent task. Para sa GitHub, bigyan ang agent user ng sarili nitong gh login na may fine-grained token na limitado sa iisang repository na pinagtatrabahuhan nito, upang ang gh auth token sa loob ng session na iyon ay magbalik ng credential na walang access sa iba pang resource. Unahin ang paglimita 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 agent. Patakbuhin ang mga ito bilang user ng agent, hindi bilang ikaw.

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/user

Dapat walang ma-print ang una. Dapat mag-print ang ikalawa ng 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: nangangahulugang walang sariling GitHub credential na dala ang agent kapag 401, at may dala naman itong credential kapag 200. Kaya dapat mong malaman kung aling token ito. Kung nagpapatakbo ka ng mga agent nang walang manual na pag-monitor, saklaw ng pagkontrol sa mga gastos ng AI agent sa isang VPS ang mga limitasyon sa budget na kaakibat 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 mga instruction mo at alin ang text na na-fetch nito. Nabibigo ang anumang control na nakadepende sa tamang pagpili ng model sa unang pagkakataong nakakumbinsi ang injected instruction, kaya dapat nasa operating system o network ang control.

Talaga bang masama ang environment variable para sa mga secret ng agent?

Masama ang mga ito sa isang partikular na paraan: namamana ang mga ito. Nakakakuha ng kopya ang bawat child process na ini-spawn 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 ang mga ito ng anumang pinapatakbo ng agent nang hindi na kailangang ipasa ng agent. Nililimitahan ng file na binabasa sa mismong oras ng paggamit, gamit ang LoadCredential= o gateway, ang exposure sa sandaling iyon lamang.

Nalulutas ba nito nang mag-isa ang paglalagay ng mga secret sa vault?

Bahagya lamang. Inaayos ng vault ang storage. Kung ikaw ang nagho-host ng vault, kailangan itong dumaan sa sarili nitong hardening pass, dahil karaniwang nabibreach ang isang Vaultwarden server sa admin token o backup file nito, hindi sa mga naka-encrypt na item na hawak nito. 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 agent ang nag-fetch 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 na malalaman pagkatapos mangyari, at ito ang dahilan kung bakit kailangan ang gateway. Kung wala nito, kalat ang ebidensiya sa shell history, transcript ng agent, at outbound connection logs na malamang ay hindi mo iniingatan. Kapag may credential gateway, bawat paggamit ng credential ay isang linya na may agent identity at timestamp. Kung pinaghihinalaan mong may leak, i-rotate muna ang key at saka mag-imbestiga. Mura ang rotation, pero hindi ang katiyakan.

Ano ang minimum na dapat kong gawin ngayon?

Ilipat ang bawat .env file palabas 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 sinasara ang pinakakaraniwang path: binabasa ng agent ang 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 hakbang para sa anumang agent runtime, kabilang ang ligtas na pagpapatakbo ng autonomous agent sa isang VPS.