Cara Menyimpan Rahsia di Luar Ejen AI
Kunci API dalam ejen AI boleh bocor melalui prompt injection. Gunakan token jangka pendek berskop terhad di sebalik gerbang kelayakan, bukan kunci sebenar.
Maksud menyimpan rahsia di luar 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 di luar ejen bermaksud memberinya pemegang dan bukannya kunci: token berjangka pendek dengan skop terhad, atau ruang letak yang digantikan dengan nilai sebenar oleh komponen lain di sempadan rangkaian.
Ini bukan cerita tentang model yang menjadi berniat jahat. 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 prompt injection. Apabila perkara ini berlaku, skop kerosakan ditentukan tepat oleh satu perkara: perkara yang boleh dibaca oleh proses itu. Jika anda belum menetapkan sempadan, menjalankan ejen pengekodan dengan selamat pada pelayan menerangkan tahap 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 daripada pelayan orang yang tidak dikenali. Sekarang lihat perkara yang terdapat pada cakera berdekatan ejen itu.
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:
curlataufetchkeluar ke mana-mana hos, dengan nilai dalam rentetan pertanyaan.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. Nilai itu tetap boleh keluar 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 working tree ialah rahsia dalam tetingkap konteks
Ejen membaca fail. Fail .env dalam repositori yang sedang digunakan oleh ejen akan dibaca. Setelah dibaca, fail itu berada dalam tetingkap konteks. Ini bermakna kandungannya terdapat dalam transkrip, dalam mana-mana log yang anda simpan dan dalam apa-apa sahaja yang ditulis oleh ejen seterusnya.
Sebelum ini, apabila kunci berada dalam tree 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 dipindahkan keluar daripada capaian ejen:
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 itu kerana working tree tidak lagi mengandungi fail tersebut. 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)"]
}
}Ini menghalang ejen daripada membuka fail secara tidak sengaja semasa meneroka. Namun, peraturan ini tidak menghalang arahan yang disuntik daripada menjalankan base64 .env kerana arahan itu ialah arahan shell, bukan pembacaan fail. Sama ada anda akan diminta sebelum arahan itu dijalankan bergantung pada mod kebenaran sesi. Mod automatik menjadi lalai Claude Code pada Ogos 2026, jadi pelayan yang tidak anda pantau akan menjalankan lebih banyak arahan tersebut tanpa meminta pengesahan. Had yang sama terpakai pada apa-apa yang membentuk tabiat ejen dan bukannya kebenarannya: skill yang mengehadkan ejen kepada perubahan terkecil yang berfungsi menghalang satu proses daripada meneroka fail yang tidak sepatutnya dibukanya, tetapi perkara itu masih sekadar nasihat yang boleh diubah oleh model melalui arahan. Anggap konfigurasi sebagai pengadang dan kebenaran sistem fail sebagai dinding. Pembahagian yang sama terpakai dalam container: fail env dan rahsia dalam Docker Compose merangkumi versi masalah ini pada satu lapisan di bawah.
Berikan setiap ejen pengguna tanpa keistimewaan sendiri
Jika ejen berjalan sebagai pengguna anda, ejen itu mewarisi kunci SSH, kelayakan cloud 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 memaparkan kunci, direktori rumah anda boleh dibaca oleh kumpulan atau pengguna lain, dan chmod 700 ~ membetulkannya. Jangan tambahkan pengguna ejen kepada sudo, dan jangan berikan peraturan NOPASSWD yang lebih luas daripada satu arahan yang benar-benar diperlukan. Pengguna dengan keistimewaan minimum pada VPS menerangkan perincian kumpulan dan sudoers. Kekalkan pengasingan ini apabila anda menjalankan lebih daripada satu sesi pada pelayan, kerana satu sesi Claude Code boleh menghantar teks terus kepada sesi lain, dan apa-apa yang disimpan oleh sesi pertama boleh merentasi saluran itu dalam satu mesej.
Satu lagi sempadan wajar ditambahkan pada VPS cloud. Perkhidmatan metadata instance menjawab pada alamat link local yang tetap, dan lazimnya 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 perkara ini dari sisi ejen. sudo -u agent-review curl -s --max-time 3 http://169.254.169.254/ sepatutnya tidak memaparkan apa-apa dan keluar dengan status bukan sifar, kerana paket itu ditolak sebelum meninggalkan pelayan.
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 setempat, dan get laluan itu menggantikan ruang letak dengan rahsia sebenar semasa permintaan keluar. Rahsia tersebut disimpan dalam storan get laluan, dalam proses yang berbeza dan dimiliki oleh pengguna yang berbeza.
OneCLI ialah salah satu pelaksanaan sumber terbuka bagi corak ini. OneCLI dilesenkan di bawah Apache-2.0 dan dijalankan sebagai container 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 --waitDashboard mendengar pada port 10254 dan get laluan pada port 10255. Anda menyimpan kelayakan sebenar sekali sahaja. Kemudian, anda memberikan setiap ejen nilai ruang letak sebagai ganti kunci, bersama-sama access token terskop miliknya sendiri, yang dihantar dalam header Proxy-Authorization. Get laluan memadankan permintaan keluar berdasarkan host dan path, menyahsulit kelayakan yang sepadan, lalu menggantikannya. Persekitaran ejen tidak menyimpan apa-apa yang bernilai untuk dicuri.
Nilai utama di sini bukan penyulitan. Nilainya ialah soalan "apakah yang digunakan oleh ejen ini, dan bila" boleh dijawab melalui pertanyaan log. Anda membaca satu jejak audit dan tidak perlu meneka persekitaran mana antara enam persekitaran yang menyimpan salinan kunci.
Serahkan rahsia kepada proses, bukan kepada persekitaran
Jika anda menjalankan ejen melalui systemd, anda tidak memerlukan pemboleh ubah persekitaran langsung. LoadCredential= meletakkan rahsia dalam direktori peribadi yang hanya boleh dibaca oleh servis tersebut. Rahsia itu didedahkan sebagai %d dalam fail unit dan sebagai $CREDENTIALS_DIRECTORY di dalam proses. Nilai tersebut tidak pernah muncul dalam /proc/<pid>/environ. Oleh itu, ps eww tidak dapat memaparkannya, dan direktori itu dipadamkan apabila servis berhenti.
Sulitkan kelayakan itu untuk mesin terlebih dahulu. Perintah ini diambil daripada dokumentasi systemd dan berfungsi pada systemd 250 atau lebih baharu, termasuk 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 memaparkan 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 hanya berlaku pada ketika itu. Pemboleh ubah persekitaran kekal sepanjang hayat proses dan turut tersedia kepada setiap proses anak yang dilancarkannya.
Utamakan token berjangka pendek berbanding kunci berjangka panjang
Kunci yang tidak pernah luput tempoh masih sah apabila muncul semula, beberapa bulan kemudian, dalam log atau transkrip. Jika servis menyediakan token sesi, gunakan token sesi itu dan tetapkan tempoh sah yang paling singkat yang masih mencukupi untuk tugas tersebut.
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 (security token service), dan biasanya tempoh itu mencukupi untuk satu tugas ejen. Untuk GitHub, berikan pengguna ejen gh log masuk tersendiri dengan token berbutiran halus yang dihadkan kepada satu repositori yang digunakan, supaya gh auth token dalam sesi itu hanya mengembalikan sesuatu yang tidak boleh mengakses apa-apa yang lain. Hadkan skop mengikut sumber terlebih dahulu, kemudian mengikut masa.
Sahkan, kemudian teruskan pengesahan
Selepas mengubah persediaan ejen, jalankan tiga semakan. 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/userPerintah pertama sepatutnya tidak memaparkan apa-apa. Perintah kedua sepatutnya memaparkan ls: cannot open directory '/home/you/': Permission denied. Perintah ketiga menunjukkan identiti yang dipersembahkan oleh laluan rangkaian ejen. Inilah persoalan yang hendak dijawab oleh corak get laluan: 401 bermaksud ejen tidak membawa kelayakan GitHub sendiri, manakala 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 supaya 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 suntikan kelihatan meyakinkan. Oleh itu, kawalan tersebut perlu dilaksanakan dalam sistem pengendalian atau rangkaian.
Adakah pemboleh ubah persekitaran benar-benar begitu berisiko untuk rahsia ejen?
Pemboleh ubah ini berisiko dalam satu perkara khusus: pemboleh ubah itu diwarisi. Setiap proses anak yang dimulakan oleh ejen menerima salinannya, termasuk skrip binaan, pelaksana ujian dan mana-mana hook pemasangan pakej. Pemboleh ubah itu juga boleh dibaca melalui /proc/<pid>/environ oleh pengguna yang sama. Oleh itu, apa-apa sahaja yang dijalankan oleh ejen boleh membacanya tanpa ejen menghantarnya. Fail yang dibaca hanya pada masa penggunaan, dengan LoadCredential= atau gateway, mengehadkan pendedahan kepada masa tersebut.
Adakah menyimpan rahsia dalam vault menyelesaikan masalah ini dengan sendirinya?
Hanya sebahagian. Vault menyelesaikan masalah penyimpanan. Jika anda mengehos vault itu sendiri, vault tersebut memerlukan proses pengukuhan keselamatan tersendiri, kerana pelayan Vaultwarden biasanya diceroboh melalui token pentadbir atau fail sandarannya, bukan melalui item yang disulitkan di dalamnya. Vault tidak menyelesaikan langkah terakhir, iaitu apabila sesuatu mengambil rahsia daripada vault dan menyerahkannya kepada ejen sebagai pemboleh ubah persekitaran. Keadaan itu mengembalikan anda kepada masalah asal. Perkara yang penting ialah pihak yang melakukan penggantian nilai tersebut. Jika ejen mendapatkan rahsia itu, ejen memiliki rahsia tersebut. Jika gateway atau sistem init melakukan penggantian di luar proses ejen, ejen tidak pernah memegangnya.
Bagaimanakah saya tahu sama ada ejen telah membocorkan sesuatu?
Biasanya, anda tidak dapat mengetahuinya selepas kejadian. Itulah sebabnya gateway diperlukan. Tanpa gateway, bukti anda berselerak dalam sejarah shell, transkrip ejen dan log sambungan keluar yang mungkin tidak anda simpan. Dengan gateway kelayakan, setiap penggunaan kelayakan direkodkan pada satu baris bersama identiti ejen dan cap masa. Jika anda mengesyaki kebocoran, putarkan kunci dahulu dan lakukan siasatan kemudian. Putaran kunci murah, manakala kepastian tidak.
Apakah perkara minimum yang perlu saya lakukan hari ini?
Pindahkan setiap fail .env keluar daripada direktori yang digunakan oleh ejen anda, dan cipta seorang pengguna tanpa keistimewaan bagi setiap ejen. 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. Gateway 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.