SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-08-29

Cara Mencegah Kebocoran API Key pada Agen AI

Agen AI dapat membocorkan kunci API melalui injeksi prompt. Pelajari cara menggunakan token berumur pendek dan gateway kredensial untuk membatasi akses tanpa memberikan kunci asli.

Apa arti menjaga rahasia agar tidak diakses agen AI

Agen AI adalah proses Linux normal yang menjalankan perintah. Setiap variabel lingkungan yang dimiliki proses tersebut dapat dibaca oleh kode yang dijalankannya, sehingga kunci API dalam lingkungan agen adalah kunci yang dapat dikirimkan agen ke host mana pun yang dapat dijangkaunya. Menjaga rahasia agar tidak diakses agen berarti memberikan handle alih-alih kunci tersebut: token dengan cakupan terbatas dan masa berlaku singkat, atau placeholder yang akan ditukar oleh sistem lain dengan nilai sebenarnya di batas jaringan.

Ini bukan cerita tentang model yang berubah menjadi jahat. Mekanismenya jauh lebih sederhana. Agen membaca halaman web, README, atau komentar issue yang berisi instruksi, lalu agen tersebut mengikutinya, karena bagi model bahasa tidak ada perbedaan antara teks yang Anda tulis dan teks yang diambilnya. Itulah prompt injection. Setelah hal itu terjadi, kerusakan dibatasi oleh satu hal saja: apa yang dapat dibaca oleh proses tersebut. Jika Anda belum menetapkan batasan, menjalankan agen pengodean dengan aman di server membahas tingkatan isolasi yang menjadi dasar panduan ini.

Model ancaman dalam istilah sederhana

Jalankan ini sebagai pengguna yang menjalankan agen Anda.

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

Setiap baris yang dicetaknya berjarak satu permintaan HTTP dari server orang asing. Sekarang perhatikan apa yang ada di disk di dekat agen tersebut.

grep -rIl --exclude-dir=.git -e 'API_KEY' -e 'SECRET' ~/projects
find ~ -maxdepth 3 -name '.env' -o -name 'credentials' -o -name '*.pem'

Agen dengan akses shell tidak memerlukan eksploitasi cerdas untuk memindahkan data tersebut. Empat jalur biasa dapat melakukan pekerjaan itu, dan keempatnya terlihat seperti aktivitas normal di log:

  • curl atau fetch keluar ke host mana pun, dengan nilai di dalam query string.
  • git commit dan git push ke repositori yang dapat ditulis oleh agen.
  • Skrip instalasi paket, yang menjalankan kode arbitrer sebagai pengguna agen.
  • Pencarian DNS untuk hostname yang berisi nilai tersebut, yang tetap terkirim meskipun akses HTTP keluar diblokir.

Anda tidak dapat menyelesaikan masalah ini hanya dengan meninjau kode. Perbaikannya adalah memastikan tidak ada data berharga yang berada dalam jangkauan.

Rahasia di dalam working tree adalah rahasia di dalam context window

Agen membaca file. File .env di dalam repositori tempat agen bekerja akan dibaca, dan setelah dibaca, file tersebut berada di dalam context window. Ini berarti file tersebut ada di dalam transkrip, di log apa pun yang Anda simpan, dan di apa pun yang ditulis agen selanjutnya.

Sebelumnya, dengan kunci yang berada di dalam tree tempat agen bekerja:

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

Setelahnya, dengan file dipindahkan ke luar jangkauan:

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

Pengguna agen tidak dapat lagi membuka file tersebut karena working tree tidak lagi memuatnya. Aturan penolakan (deny rules) di dalam konfigurasi agen itu sendiri adalah lapisan kedua, bukan lapisan pertama. Claude Code membaca aturan izin dari .claude/settings.json di dalam proyek:

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

Hal tersebut mencegah kesalahan tidak disengaja di mana agen membuka file saat melakukan eksplorasi. Langkah ini tidak menghentikan instruksi yang disuntikkan untuk menjalankan base64 .env, karena itu adalah perintah shell dan bukan pembacaan file. Apakah Anda akan dimintai persetujuan sebelum perintah tersebut dijalankan bergantung pada mode izin sesi, dan auto mode menjadi default Claude Code pada Agustus 2026, sehingga server yang tidak Anda awasi akan menjalankan lebih banyak perintah tersebut tanpa diminta. Batasan yang sama berlaku untuk apa pun yang membentuk kebiasaan agen alih-alih izinnya: skill yang menahan agen pada perubahan terkecil yang berhasil mencegah eksekusi meluas ke file yang tidak seharusnya dibuka, tetapi itu tetap berupa saran yang bisa diabaikan oleh model. Anggap konfigurasi sebagai pagar pengaman dan izin sistem file sebagai temboknya. Pemisahan yang sama berlaku di dalam container: env files dan rahasia di Docker Compose membahas versi masalah ini satu lapisan di bawahnya.

Berikan setiap agen pengguna tanpa hak akses istimewa (unprivileged)

Jika agen berjalan sebagai Anda, agen tersebut akan mewarisi kunci SSH, kredensial cloud, dan riwayat shell Anda. Pengguna terpisah hanya memerlukan satu perintah dan menghilangkan semua risiko tersebut.

sudo adduser --disabled-password --gecos "" agent-review
sudo chmod 700 /home/agent-review
sudo -u agent-review cat ~/.ssh/id_ed25519

Baris terakhir harus gagal dengan cat: /home/you/.ssh/id_ed25519: Permission denied. Jika baris tersebut menampilkan kunci, berarti direktori home Anda dapat dibaca oleh grup atau publik, dan chmod 700 ~ akan memperbaikinya. Jangan tambahkan pengguna agen ke sudo, dan jangan berikan aturan NOPASSWD yang lebih luas daripada satu perintah yang benar-benar dibutuhkannya. Pengguna dengan hak akses paling rendah di VPS membahas detail grup dan sudoers. Ingat pemisahan tersebut setelah Anda menjalankan lebih dari satu sesi di server, karena satu sesi Claude Code dapat mengirim teks langsung ke sesi lain, dan apa pun yang dipegang oleh sesi pertama dapat melintasi saluran tersebut dalam satu pesan.

Satu batasan lagi perlu ditambahkan pada VPS cloud. Layanan metadata instance merespons pada alamat link-local yang tetap, dan sering kali memberikan kredensial peran kepada siapa pun yang memintanya.

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

Periksa dari sisi agen. sudo -u agent-review curl -s --max-time 3 http://169.254.169.254/ seharusnya tidak menampilkan apa pun dan keluar dengan status non-nol, karena paket ditolak sebelum meninggalkan server.

Menyuntikkan kredensial di batas sistem

Pola yang benar-benar menyelesaikan masalah ini adalah penyuntikan kredensial. Agen tidak pernah menyimpan kunci asli. Agen mengirimkan permintaannya melalui gateway lokal, dan gateway tersebut menukar placeholder dengan rahasia asli saat permintaan keluar. Rahasia tersebut tersimpan di penyimpanan gateway, dalam proses yang berbeda, dan dimiliki oleh pengguna yang berbeda.

OneCLI adalah salah satu implementasi sumber terbuka untuk hal ini, dengan lisensi Apache-2.0, dan berjalan sebagai kontainer di samping agen. Per Juli 2026, proyek ini mendokumentasikan pengaturan berikut:

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

Dasbor mendengarkan pada port 10254 dan gateway pada 10255. Anda menyimpan kredensial asli satu kali, lalu memberikan nilai placeholder kepada setiap agen sebagai pengganti kunci beserta token akses lingkupnya sendiri, yang dikirimkan dalam header Proxy-Authorization. Gateway mencocokkan permintaan keluar berdasarkan host dan path, mendekripsi kredensial yang cocok, lalu menggantinya. Lingkungan agen tidak menyimpan apa pun yang berharga untuk dicuri.

Nilai dari pendekatan ini bukan terletak pada enkripsinya. Nilainya adalah pertanyaan "apa yang digunakan agen ini, dan kapan" menjadi sebuah kueri log. Anda membaca satu jejak audit alih-alih menebak lingkungan mana dari enam lingkungan yang menyimpan salinan kunci tersebut.

Berikan rahasia ke proses, bukan ke environment

Jika Anda menjalankan agen di bawah systemd, Anda sama sekali tidak memerlukan variabel environment. LoadCredential= menempatkan rahasia di direktori privat yang hanya dapat dibaca oleh layanan tersebut, diekspos sebagai %d dalam file unit dan sebagai $CREDENTIALS_DIRECTORY di dalam proses. Nilai tersebut tidak pernah muncul di /proc/<pid>/environ, sehingga ps eww tidak dapat menampilkannya, dan direktori tersebut akan hilang saat layanan berhenti.

Enkripsi kredensial ke mesin terlebih dahulu. Perintah-perintah ini berasal dari dokumentasi systemd dan berfungsi pada systemd 250 atau yang lebih baru, yang mencakup 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_key

Perintah terakhir mencetak sk-example-value. Itu membuktikan bahwa file terenkripsi dapat didekripsi di host ini. Kemudian referensikan dari 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

Kode agen Anda membuka file di $AGENT_KEY_FILE saat membutuhkan nilainya. Pembacaan file hanya berlangsung sesaat. Variabel environment bertahan selama masa hidup proses, di setiap child yang dibuatnya.

Utamakan token berumur pendek daripada kunci berumur panjang

Kunci yang tidak pernah kedaluwarsa akan tetap valid kapan pun kunci tersebut muncul, bahkan berbulan-bulan kemudian, di dalam log atau transkrip. Jika layanan menawarkan token sesi, gunakan token sesi tersebut dan atur masa berlaku sesingkat mungkin sesuai kebutuhan pekerjaan Anda.

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

Lima belas menit adalah durasi minimum yang diterima oleh AWS STS (security token service), dan durasi ini biasanya cukup untuk satu tugas agen. Untuk GitHub, berikan pengguna agen login gh miliknya sendiri dengan token yang memiliki cakupan terbatas (fine-grained) pada satu repositori tempat ia bekerja, sehingga gh auth token di dalam sesi tersebut akan menghasilkan sesuatu yang tidak dapat mengakses hal lain. Lakukan pembatasan berdasarkan sumber daya terlebih dahulu, kemudian berdasarkan waktu.

Verifikasi, lalu terus lakukan verifikasi

Tiga pemeriksaan perlu dijalankan setelah perubahan apa pun pada konfigurasi agen. Jalankan perintah tersebut sebagai pengguna agen, 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/user

Pemeriksaan pertama seharusnya tidak menampilkan apa pun. Pemeriksaan kedua seharusnya menampilkan ls: cannot open directory '/home/you/': Permission denied. Pemeriksaan ketiga memberi tahu Anda identitas apa yang disajikan oleh jalur jaringan agen, yang merupakan pertanyaan yang dijawab oleh pola gateway: 401 berarti agen tidak membawa kredensial GitHub miliknya sendiri, dan 200 berarti agen tersebut membawanya, sehingga Anda harus mengetahui token mana yang digunakan. Jika Anda menjalankan agen tanpa pengawasan, mengendalikan biaya agen AI di VPS membahas batasan anggaran yang dipasangkan dengan batasan akses ini.

FAQ

Bisakah saya sekadar memercayai model agar tidak membocorkan kunci saya?

Tidak, karena model bukanlah penyerang dalam model ancaman ini. Agen membaca teks dari halaman web, repositori, dan pelacak masalah (issue tracker), dan teks tersebut dapat berisi instruksi. Model tidak memiliki cara yang andal untuk membedakan instruksi Anda dari teks yang diambilnya. Kontrol apa pun yang bergantung pada pilihan model yang tepat akan gagal saat instruksi injeksi pertama yang meyakinkan muncul, sehingga kontrol harus ditempatkan di sistem operasi atau jaringan.

Apakah variabel lingkungan benar-benar seburuk itu untuk rahasia agen?

Variabel tersebut buruk dalam satu hal spesifik: variabel tersebut diwariskan. Setiap proses anak yang dijalankan agen mendapatkan salinannya, termasuk skrip build, test runner, dan hook instalasi paket apa pun. Variabel tersebut juga dapat dibaca melalui /proc/<pid>/environ oleh pengguna yang sama, sehingga apa pun yang dijalankan agen dapat membacanya tanpa perlu diteruskan oleh agen. File yang dibaca pada saat penggunaan, dengan LoadCredential= atau gateway, membatasi paparan hanya pada saat itu saja.

Apakah menyimpan rahasia di dalam vault menyelesaikan masalah ini dengan sendirinya?

Hanya sebagian. Vault memperbaiki penyimpanan. Jika Anda melakukan self-host pada vault tersebut, vault itu memerlukan langkah pengerasan (hardening) tersendiri, karena server Vaultwarden biasanya dibobol melalui token admin atau file cadangannya, bukan melalui item terenkripsi yang disimpannya. Hal ini tidak memperbaiki langkah terakhir, di mana sesuatu menarik rahasia keluar dari vault dan memberikannya kepada agen sebagai variabel lingkungan, yang mengembalikan Anda ke titik awal. Yang penting adalah siapa yang melakukan substitusi. Jika agen mengambil rahasia tersebut, maka agen memegang rahasia tersebut. Jika gateway atau sistem init melakukan substitusi di luar proses agen, agen tidak pernah memegangnya.

Bagaimana saya tahu apakah agen sudah membocorkan sesuatu?

Biasanya Anda tidak dapat mengetahuinya setelah kejadian, itulah argumen untuk penggunaan gateway. Tanpa gateway, bukti Anda tersebar di riwayat shell, transkrip agen, dan log koneksi keluar yang mungkin tidak Anda simpan. Dengan gateway kredensial, setiap penggunaan kredensial adalah satu baris log dengan identitas agen dan stempel waktu. Jika Anda mencurigai adanya kebocoran, lakukan rotasi kunci terlebih dahulu, baru kemudian lakukan investigasi. Rotasi itu murah, sedangkan kepastian tidak.

Apa hal minimum yang harus saya lakukan hari ini?

Pindahkan setiap file .env keluar dari direktori tempat agen Anda bekerja, dan buat satu pengguna tanpa hak akses istimewa (unprivileged user) untuk setiap agen. Kedua perubahan tersebut memakan waktu sekitar sepuluh menit dan menutup jalur yang paling umum, yaitu agen yang membaca file kredensial yang seharusnya tidak perlu berada di dekat kode. Gateway dan token berumur pendek adalah langkah berikutnya, bukan langkah pertama. Titik awal yang sama berlaku untuk runtime agen apa pun, termasuk menjalankan agen otonom dengan aman di VPS.