Jinsi ya kulinda API keys kwenye AI agents
AI agent anaweza kuvujisha API keys kupitia prompt injection. Epuka hatari hii kwa kutumia token zenye muda mfupi na credential gateway badala ya kutoa funguo halisi.
Maana ya kutoweka siri ndani ya AI agents
AI agent ni mchakato wa kawaida wa Linux unaotekeleza amri. Kila variable ya mazingira (environment variable) inayoshikiliwa na mchakato huo inaweza kusomwa na msimbo unaouendesha, kwa hivyo API key iliyo kwenye mazingira ya agent ni ufunguo ambao agent anaweza kuutuma kwa host yoyote anayoweza kuifikia. Kutoweka siri ndani ya agent kunamaanisha kumpa kishikio (handle) badala ya ufunguo wenyewe: token yenye muda mfupi na uwezo mdogo, au kishika nafasi (placeholder) ambacho kitu kingine hubadilisha na thamani halisi kwenye mpaka wa mtandao.
Hii si hadithi kuhusu model inayogeuka kuwa mbaya. Utaratibu huu ni wa kawaida zaidi. Agent husoma ukurasa wa wavuti, README, au maoni ya issue yaliyo na maelekezo, na huyafuata, kwa sababu kwa language model hakuna tofauti kati ya maandishi uliyoandika wewe na maandishi iliyoyachota. Hiyo ni prompt injection. Mara tu inapotokea, uharibifu hupimwa kwa kitu kimoja tu: kile ambacho mchakato unaweza kusoma. Ikiwa bado hujaweka mpaka, kuendesha coding agent kwa usalama kwenye seva inashughulikia hatua za kutenga (isolation) ambazo mwongozo huu unajengewa juu yake.
Mfumo wa vitisho kwa lugha rahisi
Tekeleza amri hii kama mtumiaji anayeendesha agent yako.
tr '\0' '\n' < /proc/self/environ | grep -iE 'key|token|secret|password'Kila mstari unaochapishwa ni ombi moja la HTTP mbali na seva ya mgeni. Sasa angalia kilichopo kwenye diski karibu na agent.
grep -rIl --exclude-dir=.git -e 'API_KEY' -e 'SECRET' ~/projects
find ~ -maxdepth 3 -name '.env' -o -name 'credentials' -o -name '*.pem'Agent mwenye uwezo wa shell hahitaji exploit ya kipekee ili kutoa data hiyo nje. Njia nne za kawaida hufanikisha kazi hiyo, na zote nne huonekana kama shughuli za kawaida kwenye log:
curlaufetchya kutoka nje kwenda kwa host yoyote, ikiwa na thamani hiyo kwenye query string.git commitnagit pushkwenda kwenye repository ambayo agent anaweza kuandikia.- Script ya kusakinisha kifurushi (package), ambayo huendesha code yoyote kama mtumiaji wa agent.
- DNS lookup ya hostname iliyo na thamani hiyo, ambayo hupita hata kama HTTP egress imefungwa.
Huwezi kutatua hili kwa kukagua tu. Suluhisho ni kuhakikisha kuwa hakuna kitu cha thamani kinachoweza kufikiwa.
Siri iliyo kwenye working tree ni siri iliyo kwenye context window
Wakala husoma faili. Faili la .env lililo kwenye hazina (repository) inayofanyiwa kazi litasomwa, na mara tu linapokuwa kwenye context window, linakuwa kwenye nakala ya mazungumzo, kwenye log yoyote unayotunza, na kwenye chochote ambacho wakala ataandika baadaye.
Hapo awali, ufunguo ukiwa kwenye tree ambamo wakala anafanyia kazi:
cd ~/projects/billing
cat .env
# STRIPE_SECRET_KEY=sk_live_...
# DATABASE_URL=postgres://app:hunter2@db.internal:5432/billingBaada ya hapo, faili likiwa limehamishwa ili lisiweze kufikiwa:
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/.envMtumiaji wa wakala hawezi tena kufungua faili hilo, kwa sababu working tree halina tena faili hilo. Sheria za kukataa (deny rules) kwenye usanidi wa wakala wenyewe ni safu ya pili ya ulinzi, si ya kwanza. Claude Code husoma sheria za ruhusa kutoka .claude/settings.json kwenye mradi:
{
"permissions": {
"deny": ["Read(./.env)", "Read(./secrets/**)", "Read(./**/*.pem)"]
}
}Hiyo huzuia kosa la bahati mbaya la wakala kufungua faili wakati anachunguza mfumo. Haizuii maelekezo yaliyoingizwa (injected instruction) kuendesha base64 .env, kwa sababu hiyo ni amri ya shell na si usomaji wa faili. Kikomo hicho hicho kinahusu chochote kinachounda tabia za wakala badala ya ruhusa zake: ustadi unaomfanya wakala azingatie mabadiliko madogo zaidi yanayofanya kazi huzuia utekelezaji usitangatange kwenye faili ambazo halikupaswa kuzifungua, lakini bado ni ushauri ambao modeli inaweza kushawishiwa kuupuuza. Chukulia usanidi kama kizuizi cha usalama (guardrail) na ruhusa za mfumo wa faili kama ukuta. Mgawanyo huo huo unatumika ndani ya containers: faili za env na siri kwenye Docker Compose inashughulikia toleo la tatizo hili katika safu moja chini.
Mpe kila wakala mtumiaji wake asiye na upendeleo (unprivileged)
Ikiwa wakala anaendeshwa kama wewe, anarithi funguo zako za SSH, vitambulisho vyako vya cloud, na historia ya shell yako. Mtumiaji tofauti anagharimu amri moja tu na huondoa hatari hizo zote.
sudo adduser --disabled-password --gecos "" agent-review
sudo chmod 700 /home/agent-review
sudo -u agent-review cat ~/.ssh/id_ed25519Mstari wa mwisho lazima ushindwe kwa cat: /home/you/.ssh/id_ed25519: Permission denied. Ikiwa utachapisha ufunguo badala yake, saraka yako ya nyumbani (home directory) inaweza kusomwa na kikundi au dunia nzima, na chmod 700 ~ inarekebisha hilo. Usimwongeze mtumiaji wa wakala kwenye sudo, na usimpe sheria ya NOPASSWD pana zaidi kuliko amri moja anayohitaji kweli. Watumiaji wenye upendeleo mdogo kwenye VPS inaelezea kwa kina kuhusu vikundi na sudoers.
Kikomo kingine kinastahili kuongezwa kwenye VPS ya cloud. Huduma ya metadata ya instance hujibu kwenye anwani maalum ya link local, na mara nyingi hutoa vitambulisho vya role kwa chochote kinachouliza.
sudo iptables -A OUTPUT -m owner --uid-owner agent-review -d 169.254.169.254 -j REJECTKagua hili kutoka upande wa wakala. sudo -u agent-review curl -s --max-time 3 http://169.254.169.254/ inapaswa isichapishe chochote na itoke kwa status isiyo ya sifuri (non-zero), kwa sababu pakiti hiyo hukataliwa kabla haijatoka kwenye seva.
Ingiza kitambulisho kwenye mpaka wa mfumo
Muundo unaotatua tatizo hili ni uingizaji wa kitambulisho (credential injection). Wakala (agent) haushiki kamwe ufunguo halisi. Hutuma ombi lake kupitia lango la ndani (local gateway), na lango hilo hubadilisha kishika-nafasi (placeholder) na siri halisi wakati ombi linapotoka. Siri hiyo hukaa kwenye hifadhi ya lango, katika mchakato tofauti, unaomilikiwa na mtumiaji tofauti.
OneCLI ni utekelezaji mmoja wa chanzo huria wa mbinu hii, yenye leseni ya Apache-2.0, na huendeshwa kama kontena kando ya wakala. Kufikia Julai 2026, mradi huu unaelezea usanidi huu:
git clone https://github.com/onecli/onecli.git
cd onecli
docker compose -f docker/docker-compose.yml up -d --waitDashibodi husikiliza kwenye port 10254 na lango kwenye 10255. Unahifadhi kitambulisho halisi mara moja, kisha unampa kila wakala thamani ya kishika-nafasi badala ya ufunguo, pamoja na token yake ya ufikiaji yenye upeo maalum, ambayo wakala huituma ndani ya header ya Proxy-Authorization. Lango hulinganisha ombi linalotoka kwa kutumia host na path, husimbua kitambulisho kinacholingana, na kukibadilisha. Mazingira ya wakala hayashiki kitu chochote chenye thamani ya kuibiwa.
Thamani ya mbinu hii si usimbaji fiche. Ni kwamba swali la "wakala huyu alitumia nini, na lini" linakuwa swali la logi. Unasoma njia moja ya ukaguzi (audit trail) badala ya kukisia ni yapi kati ya mazingira sita yaliyoshikilia nakala ya ufunguo.
Kukabidhi siri kwa mchakato, siyo kwa mazingira
Ikiwa unaendesha agent chini ya systemd, huhitaji vigezo vya mazingira (environment variables) hata kidogo. LoadCredential= huweka siri hiyo kwenye saraka binafsi ambayo huduma hiyo pekee inaweza kuisoma, ikionyeshwa kama %d katika faili la unit na kama $CREDENTIALS_DIRECTORY ndani ya mchakato. Thamani hiyo haionekani kamwe katika /proc/<pid>/environ, kwa hivyo ps eww haiwezi kuionyesha, na saraka hiyo hupotea wakati huduma inaposimama.
Simba kitambulisho (credential) kwa mashine kwanza. Amri hizi zinatoka kwenye nyaraka za systemd na hufanya kazi kwenye systemd 250 au mpya zaidi, ambayo inajumuisha Ubuntu 24.04 na 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_keyAmri ya mwisho huchapisha sk-example-value. Hiyo inathibitisha kuwa faili lililosimbwa hufunguka (decrypt) kwenye seva hii. Kisha irejelee kutoka kwenye 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-workerMsimbo wa agent yako hufungua faili katika $AGENT_KEY_FILE inapohitaji thamani hiyo. Kusoma faili ni tukio la muda mfupi. Kigezo cha mazingira hudumu kwa maisha yote ya mchakato, katika kila mtoto (child process) inachozalisha.
Pendelea token za muda mfupi kuliko funguo za muda mrefu
Ufunguo usioisha muda wake utabaki kuwa halali wakati wowote utakapopatikana, hata miezi baadaye, ndani ya logi au nakala ya mazungumzo. Pale huduma inapotoa session token, tumia token hiyo na uweke muda mfupi zaidi wa matumizi unaoruhusiwa na kazi husika.
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/agent-readonly \
--role-session-name agent-review \
--duration-seconds 900Dakika 15 ndio muda mfupi zaidi unaokubalika na AWS STS (security token service), na kwa kawaida unatosha kwa kazi moja ya wakala. Kwa GitHub, mpe mtumiaji wa wakala login yake mwenyewe ya gh yenye token iliyopunguzwa uwezo na kuelekezwa kwenye hazina (repository) moja tu anayofanyia kazi, ili gh auth token ndani ya session hiyo irejeshe kitu kisichoweza kugusa kingine chochote. Punguza uwezo kwa rasilimali kwanza, kisha kwa muda.
Thibitisha, kisha endelea kuthibitisha
Kuna ukaguzi tatu ambazo ni muhimu kufanywa baada ya mabadiliko yoyote kwenye usanidi wa agent. Zifanye ukiwa kama mtumiaji wa agent, si kama wewe mwenyewe.
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/userUkaguzi wa kwanza haupaswi kutoa matokeo yoyote. Wa pili unapaswa kuchapisha ls: cannot open directory '/home/you/': Permission denied. Wa tatu unakuonyesha utambulisho ambao njia ya mtandao ya agent inawasilisha, ambayo ndiyo swali ambalo muundo wa gateway upo ili kulijibu: 401 inamaanisha kuwa agent haina kitambulisho chochote cha GitHub, na 200 inamaanisha kuwa inacho, hivyo unapaswa kujua ni token ipi hiyo. Ikiwa unaendesha agents bila usimamizi wa moja kwa moja, kudhibiti gharama za AI agent kwenye VPS inaelezea mipaka ya bajeti inayooana na mipaka hii ya ufikiaji.
FAQ
Je, ninaweza kuamini tu mfano huu usivujishe funguo zangu?
Hapana, kwa sababu mfano huu si mshambuliaji katika mtindo huu wa vitisho. Wakala husoma maandishi kutoka kurasa za wavuti, hazina za msimbo (repositories), na mifumo ya kufuatilia masuala (issue trackers), na maandishi hayo yanaweza kuwa na maagizo. Mfano huu hauna njia ya kuaminika ya kutofautisha maagizo yako na maandishi iliyoyachota. Udhibiti wowote unaotegemea mfano huu kuchagua kwa usahihi utafeli mara ya kwanza tu ambapo agizo lililodungwa (injected instruction) litakuwa la kushawishi, kwa hivyo udhibiti lazima uwe kwenye mfumo wa uendeshaji (OS) au mtandao badala yake.
Je, environment variables ni mbaya kweli kwa siri za wakala?
Ni mbaya kwa njia moja mahususi: hurithiwa. Kila mchakato wa mtoto (child process) ambao wakala huuanzisha hupata nakala, ikijumuisha hati ya ujenzi (build script), kimbiaji wa majaribio (test runner), na ndoano yoyote ya usakinishaji wa kifurushi. Vigezo hivi pia vinaweza kusomeka kupitia /proc/<pid>/environ na mtumiaji yuleyule, kwa hivyo chochote ambacho wakala huendesha kinaweza kuviona bila wakala kuvipitisha. Faili inayosomwa wakati wa matumizi, kwa kutumia LoadCredential= au lango (gateway), hupunguza hatari ya kufichuliwa kwa wakati huo tu.
Je, kuweka siri kwenye vault kunatatua hili peke yake?
Kwa sehemu tu. Vault hutatua uhifadhi. Haitatui hatua ya mwisho, ambapo kitu fulani huchota siri kutoka kwenye vault na kuikabidhi kwa wakala kama environment variable, jambo linalokurudisha pale ulipoanzia. Kinachojalisha ni nani anayefanya uingizwaji (substitution). Ikiwa wakala atachota siri, wakala anayo siri hiyo. Ikiwa lango au mfumo wa init utafanya uingizwaji nje ya mchakato wa wakala, wakala haishiki siri hiyo kamwe.
Nitajuaje kama wakala amekwisha vujisha kitu?
Kwa kawaida huwezi kujua baada ya tukio kutokea, ndiyo hoja ya kutumia lango. Bila lango, ushahidi wako utakuwa umetawanyika kwenye historia ya shell, nakala ya mazungumzo ya wakala, na kumbukumbu za miunganisho ya nje ambazo pengine huzihifadhi. Kwa kutumia lango la vitambulisho (credential gateway), kila matumizi ya kitambulisho ni mstari mmoja wenye utambulisho wa wakala na muhuri wa muda. Ikiwa unashuku uvujaji, badilisha ufunguo kwanza kisha ufanye uchunguzi baadaye. Kubadilisha ufunguo ni rahisi na uhakika si rahisi kupatikana.
Ni nini cha chini kabisa ninachopaswa kufanya leo?
Ondoa kila faili ya .env kutoka kwenye saraka ambazo mawakala wako hufanyia kazi, na uunde mtumiaji mmoja asiye na upendeleo (unprivileged user) kwa kila wakala. Mabadiliko hayo mawili huchukua kama dakika kumi na hufunga njia ya kawaida zaidi, ambayo ni wakala kusoma faili ya kitambulisho ambayo haikuwa na sababu ya kukaa karibu na msimbo. Lango na tokeni za muda mfupi ni hatua inayofuata, si ya kwanza. Hatua hiyo hiyo ya kuanzia inatumika kwa runtime yoyote ya wakala, ikijumuisha kuendesha wakala wa kujitegemea kwa usalama kwenye VPS.