Lindungi Rahsia Daripada Ejen AI
Kunci API dalam persekitaran ejen boleh bocor melalui satu panggilan alat. Gunakan token berskop dan berjangka pendek melalui get laluan kelayakan, bukan kunci sebenar.
Maksud menyimpan rahsia daripada ejen AI
Ejen AI ialah proses Linux biasa yang menjalankan perintah. Setiap pemboleh ubah persekitaran yang dipegang oleh proses itu boleh dibaca oleh kod yang dijalankannya. Oleh itu, kunci API dalam persekitaran ejen ialah kunci yang boleh dihantar oleh ejen ke mana-mana hos yang boleh dicapainya. Menyimpan rahsia daripada ejen bermaksud memberikannya pemegang dan bukannya kunci: token berskop dengan tempoh sah yang singkat, atau ruang letak yang ditukar oleh komponen lain kepada nilai sebenar di sempadan rangkaian.
Ini bukan kisah tentang model yang menjadi bermusuhan. Mekanismenya lebih biasa. Ejen membaca halaman web, README, atau komen isu yang mengandungi arahan, lalu mengikutinya kerana bagi model bahasa, tiada perbezaan antara teks yang anda tulis dengan teks yang diambilnya. Itulah suntikan prompt. Apabila perkara ini berlaku, tahap kerosakan dihadkan tepat oleh satu perkara: perkara yang boleh dibaca oleh proses itu. Jika anda belum menetapkan sempadan, menjalankan ejen pengekodan dengan selamat pada pelayan menerangkan peringkat pengasingan yang menjadi asas panduan ini.
Model ancaman dalam istilah mudah
Jalankan ini sebagai pengguna yang digunakan oleh ejen anda.
tr '\0' '\n' < /proc/self/environ | grep -iE 'key|token|secret|password'Setiap baris yang dicetaknya ialah satu permintaan HTTP sahaja jauhnya daripada pelayan orang yang tidak dikenali. Sekarang, lihat kandungan pada cakera berdekatan ejen tersebut.
grep -rIl --exclude-dir=.git -e 'API_KEY' -e 'SECRET' ~/projects
find ~ -maxdepth 3 -name '.env' -o -name 'credentials' -o -name '*.pem'Ejen yang mempunyai shell tidak memerlukan eksploit yang canggih untuk mengeluarkan data tersebut. Empat laluan biasa sudah mencukupi, dan keempat-empatnya kelihatan seperti kerja biasa dalam log:
- Permintaan keluar
curlataufetchke mana-mana hos, dengan nilai dalam rentetan pertanyaan. - Permintaan
git commitdangit pushke repositori yang boleh ditulis oleh ejen. - Skrip pemasangan pakej yang menjalankan kod sewenang-wenangnya sebagai pengguna ejen.
- Carian DNS bagi nama hos yang mengandungi nilai tersebut, yang tetap meninggalkan sistem walaupun egress HTTP disekat.
Anda tidak dapat menyelesaikan masalah ini hanya dengan membuat semakan. Penyelesaiannya ialah memastikan tiada data bernilai yang boleh dicapai.
Rahsia dalam pepohon kerja ialah rahsia dalam tetingkap konteks
Ejen membaca fail. Fail .env dalam repositori yang sedang digunakan akan dibaca. Selepas dibaca, fail itu berada dalam tetingkap konteks. Ini bermakna fail itu berada dalam transkrip, dalam mana-mana log yang anda simpan dan dalam apa-apa sahaja yang ditulis oleh ejen selepas itu.
Sebelum ini, apabila key berada dalam pepohon yang digunakan oleh ejen:
cd ~/projects/billing
cat .env
# STRIPE_SECRET_KEY=sk_live_...
# DATABASE_URL=postgres://app:hunter2@db.internal:5432/billingSelepas fail itu dialihkan ke luar capaian:
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/.envPengguna ejen tidak lagi boleh membuka fail tersebut kerana pepohon kerja tidak lagi mengandunginya. Peraturan penafian dalam konfigurasi ejen sendiri ialah lapisan kedua, bukan lapisan pertama. Claude Code membaca peraturan kebenaran daripada .claude/settings.json dalam projek:
{
"permissions": {
"deny": ["Read(./.env)", "Read(./secrets/**)", "Read(./**/*.pem)"]
}
}Peraturan ini menghalang ejen daripada membuka fail secara tidak sengaja semasa meneroka. Peraturan ini tidak menghalang arahan yang disuntik daripada menjalankan base64 .env kerana arahan itu ialah arahan shell, bukannya pembacaan fail. Anggap konfigurasi sebagai perlindungan asas dan kebenaran sistem fail sebagai penghalang. Pembahagian yang sama terpakai dalam container: fail env dan rahsia dalam Docker Compose menerangkan versi masalah ini pada satu lapisan lebih rendah.
Berikan setiap ejen pengguna tanpa keistimewaan sendiri
Jika ejen berjalan sebagai anda, ejen itu mewarisi kunci SSH, kelayakan awan dan sejarah shell anda. Pengguna berasingan hanya memerlukan satu arahan dan menghapuskan semua akses tersebut.
sudo adduser --disabled-password --gecos "" agent-review
sudo chmod 700 /home/agent-review
sudo -u agent-review cat ~/.ssh/id_ed25519Baris terakhir mesti gagal dengan cat: /home/you/.ssh/id_ed25519: Permission denied. Jika arahan itu mencetak kunci, direktori utama anda boleh dibaca oleh kumpulan atau semua pengguna, dan chmod 700 ~ membetulkannya. Jangan tambahkan pengguna ejen kepada sudo, dan jangan berikan aturan NOPASSWD yang lebih luas daripada satu arahan yang benar-benar diperlukan. Pengguna dengan keistimewaan minimum pada VPS menerangkan butiran kumpulan dan sudoers.
Satu lagi sempadan wajar ditambahkan pada VPS awan. Perkhidmatan metadata tika menjawab pada alamat link-local yang tetap, dan sering memberikan kelayakan peranan kepada apa-apa yang membuat permintaan.
sudo iptables -A OUTPUT -m owner --uid-owner agent-review -d 169.254.169.254 -j REJECTSemak dari sisi ejen. sudo -u agent-review curl -s --max-time 3 http://169.254.169.254/ sepatutnya tidak mencetak apa-apa dan keluar dengan kod bukan sifar kerana paket ditolak sebelum meninggalkan sistem.
Suntik kelayakan pada sempadan
Corak yang benar-benar menyelesaikan masalah ini ialah suntikan kelayakan. Ejen tidak pernah menyimpan kunci sebenar. Ejen menghantar permintaan melalui get laluan tempatan, dan get laluan menggantikan ruang letak dengan rahsia sebenar semasa permintaan keluar. Rahsia itu disimpan dalam storan get laluan, dalam proses yang berbeza dan dimiliki oleh pengguna yang berbeza.
OneCLI ialah salah satu pelaksanaan sumber terbuka bagi pendekatan ini, dilesenkan di bawah Apache-2.0, dan dijalankan sebagai kontena bersebelahan dengan ejen. Setakat July 2026, projek ini mendokumenkan persediaan berikut:
git clone https://github.com/onecli/onecli.git
cd onecli
docker compose -f docker/docker-compose.yml up -d --waitPapan pemuka mendengar pada port 10254 dan get laluan pada port 10255. Anda menyimpan kelayakan sebenar sekali, kemudian memberikan setiap ejen nilai ruang letak sebagai ganti kunci, bersama token akses berlingkupnya sendiri, yang dihantar dalam pengepala Proxy-Authorization. Get laluan memadankan permintaan keluar berdasarkan hos dan laluan, menyahsulit kelayakan yang sepadan, kemudian menggantikannya. Persekitaran ejen tidak mengandungi apa-apa yang bernilai untuk dicuri.
Nilai pendekatan ini bukan pada penyulitannya. Nilainya ialah soalan “apakah yang digunakan oleh ejen ini, dan bila” boleh dijawab melalui pertanyaan log. Anda membaca satu jejak audit, bukannya meneka persekitaran yang mana antara enam persekitaran menyimpan salinan kunci tersebut.
Serahkan rahsia kepada proses, bukan kepada persekitaran
Jika anda menjalankan ejen di bawah systemd, anda tidak memerlukan pemboleh ubah persekitaran sama sekali. LoadCredential= meletakkan rahsia dalam direktori peribadi yang hanya boleh dibaca oleh perkhidmatan tersebut, didedahkan sebagai %d dalam fail unit dan sebagai $CREDENTIALS_DIRECTORY di dalam proses. Nilai itu tidak pernah muncul dalam /proc/<pid>/environ, jadi ps eww tidak dapat memaparkannya, dan direktori tersebut dipadamkan apabila perkhidmatan berhenti.
Sulitkan kelayakan kepada mesin terlebih dahulu. Perintah ini berasal daripada dokumentasi systemd dan berfungsi pada systemd 250 atau lebih baharu, yang meliputi Ubuntu 24.04 dan 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_keyPerintah terakhir mencetak sk-example-value. Ini membuktikan bahawa fail yang disulitkan boleh dinyahsulit pada hos ini. Kemudian rujuk fail tersebut daripada 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-workerKod ejen anda membuka fail di $AGENT_KEY_FILE apabila memerlukan nilainya. Pembacaan fail berlaku seketika. Pemboleh ubah persekitaran kekal sepanjang hayat proses, termasuk dalam setiap proses anak yang diciptanya.
Utamakan token berjangka hayat pendek berbanding kunci berjangka hayat panjang
Kunci yang tidak pernah luput masih sah apabila muncul semula, beberapa bulan kemudian, dalam log atau transkrip. Jika perkhidmatan menyediakan token sesi, gunakan token sesi dan tetapkan tempoh hayat terpendek yang dibenarkan oleh tugasan.
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/agent-readonly \
--role-session-name agent-review \
--duration-seconds 900Lima belas minit ialah tempoh minimum yang diterima oleh AWS STS (perkhidmatan token keselamatan), dan tempoh ini biasanya mencukupi untuk satu tugasan ejen. Untuk GitHub, berikan pengguna ejen log masuk gh sendiri dengan token berbutir halus yang dihadkan kepada repositori tunggal yang dikendalikannya, supaya gh auth token dalam sesi itu mengembalikan sesuatu yang tidak boleh mengakses apa-apa yang lain. Hadkan skop mengikut sumber terlebih dahulu, kemudian mengikut masa.
Sahkan, kemudian teruskan pengesahan
Tiga pemeriksaan wajar dijalankan selepas sebarang perubahan pada persediaan ejen. Jalankannya sebagai pengguna ejen, bukan sebagai pengguna anda sendiri.
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/userPemeriksaan pertama sepatutnya tidak memaparkan apa-apa. Pemeriksaan kedua sepatutnya memaparkan ls: cannot open directory '/home/you/': Permission denied. Pemeriksaan ketiga memberitahu anda identiti yang didedahkan oleh laluan rangkaian ejen. Inilah persoalan yang hendak dijawab oleh corak get laluan: nilai 401 bermaksud ejen tidak membawa kelayakan GitHub sendiri, manakala nilai 200 bermaksud ejen membawanya. Oleh itu, anda perlu mengetahui token yang digunakan. Jika anda menjalankan ejen tanpa pengawasan, mengawal kos ejen AI pada VPS menerangkan had belanjawan yang sepadan dengan had akses ini.
FAQ
Bolehkah saya mempercayai model untuk tidak membocorkan kunci saya?
Tidak, kerana model bukan penyerang dalam model ancaman ini. Ejen membaca teks daripada halaman web, repositori dan penjejak isu, dan teks itu boleh mengandungi arahan. Model tidak mempunyai cara yang boleh dipercayai untuk membezakan arahan anda daripada teks yang diperolehnya. Sebarang kawalan yang bergantung pada model untuk membuat pilihan yang betul akan gagal apabila arahan yang disuntik kelihatan meyakinkan. Oleh itu, kawalan tersebut mesti berada dalam sistem pengendalian atau rangkaian.
Adakah pemboleh ubah persekitaran benar-benar berbahaya untuk rahsia ejen?
Pemboleh ubah ini berbahaya dalam satu aspek khusus: pemboleh ubah ini diwarisi. Setiap proses anak yang dilancarkan oleh ejen menerima salinan, termasuk skrip binaan, pelaksana ujian dan sebarang cangkuk pemasangan pakej. Pemboleh ubah ini juga boleh dibaca melalui /proc/<pid>/environ oleh pengguna yang sama. Oleh itu, apa-apa yang dijalankan oleh ejen boleh membacanya tanpa ejen menghantarnya. Fail yang dibaca pada masa diperlukan, menggunakan LoadCredential= atau get laluan, mengehadkan pendedahan kepada tempoh tersebut.
Adakah menyimpan rahsia dalam peti besi menyelesaikan masalah ini dengan sendirinya?
Hanya sebahagian. Peti besi menyelesaikan masalah penyimpanan. Peti besi tidak menyelesaikan langkah terakhir, apabila sesuatu mengambil rahsia daripada peti besi dan menyerahkannya kepada ejen sebagai pemboleh ubah persekitaran. Keadaan itu mengembalikan anda kepada masalah asal. Perkara penting ialah pihak yang melaksanakan penggantian tersebut. Jika ejen mendapatkan rahsia, ejen memiliki rahsia itu. Jika get laluan atau sistem init melaksanakan penggantian di luar proses ejen, ejen tidak pernah memegangnya.
Bagaimanakah saya boleh mengetahui sama ada ejen telah membocorkan sesuatu?
Biasanya, anda tidak boleh mengetahuinya selepas kejadian. Inilah sebabnya get laluan diperlukan. Tanpa get laluan, bukti anda berpecah antara sejarah shell, transkrip ejen dan log sambungan keluar yang mungkin tidak anda simpan. Dengan get laluan kelayakan, setiap penggunaan kelayakan direkodkan dalam satu baris bersama identiti ejen dan cap masa. Jika anda mengesyaki kebocoran, putarkan kunci terlebih dahulu dan jalankan siasatan selepas itu. Putaran kunci adalah murah, manakala kepastian bukanlah sesuatu yang mudah diperoleh.
Apakah tindakan minimum yang perlu saya lakukan hari ini?
Pindahkan setiap fail .env keluar dari direktori tempat ejen anda beroperasi, dan cipta seorang pengguna tanpa keistimewaan bagi setiap ejen. Kedua-dua perubahan ini mengambil masa kira-kira sepuluh minit dan menutup laluan yang paling biasa, iaitu ejen membaca fail kelayakan yang tidak sepatutnya berada bersebelahan dengan kod. Get laluan dan token berjangka pendek ialah langkah seterusnya, bukan langkah pertama. Titik permulaan yang sama terpakai pada mana-mana masa jalan ejen, termasuk menjalankan ejen autonomi dengan selamat pada VPS.