7 Kasus Keamanan Gagal Claude Code | Insiden Nyata dan Pencegahan
Tujuh insiden keamanan nyata dengan Claude Code: kebocoran .env, penghapusan DB produksi, ledakan tagihan dan lainnya — dengan analisis penyebab dan kode pencegahan.
“Claude Code memang praktis, tapi rasanya agak menakutkan” — perasaan itu benar adanya. Alat yang powerful menimbulkan kecelakaan yang powerful juga.
Artikel ini membahas tujuh insiden keamanan nyata yang dapat terjadi saat mengembangkan dengan Claude Code, menjelaskan mengapa hal itu terjadi dan bagaimana mencegahnya dengan kode dan konfigurasi konkret. Belajarlah dari kesalahan orang lain sebelum menjadi kesalahan Anda sendiri.
Kasus 1: File .env Ter-push ke GitHub
Apa yang Terjadi
Seorang developer memberi instruksi kepada Claude Code: “Saya ingin meneruskan variabel lingkungan ke CI, tolong commit juga file .env-nya.” Claude Code dengan patuh menjalankan git add .env && git commit. Beberapa menit setelah push ke GitHub, sebuah crawler mendeteksi API key. Notifikasi Slack masuk: “Your API key has been exposed.”
Penyebab
.envtidak ada di.gitignore- Claude Code menjalankan instruksi “commit ini” secara literal
- Pengguna menyetujui dialog konfirmasi tanpa berpikir
Kode Pencegahan
1. Otomatiskan setup keamanan saat membuat proyek
# scripts/init-security.sh — jalankan setiap kali membuat proyek
#!/bin/bash
cat >> .gitignore << 'EOF'
# === Keamanan: Jangan pernah commit ini ===
.env
.env.*
.env.local
!.env.example
*.pem
*.key
*-service-account.json
credentials.json
EOF
echo "✓ Pola pengecualian keamanan ditambahkan ke .gitignore"
git add .gitignore && git commit -m "security: add .gitignore patterns"
2. Scan sebelum commit dengan Hook
.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(git add*)",
"hooks": [{
"type": "command",
"command": "git diff --cached --name-only | grep -E '^\\.env' && echo '🚨 Anda akan meng-stage file .env! Batalkan!' && exit 1 || exit 0"
}]
}
]
}
}
3. Pemulihan jika sudah ter-push
# Langkah 1: Rotasi API key segera (prioritas utama)
# Langkah 2: Hapus sepenuhnya dari riwayat git
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch .env" \
--prune-empty --tag-name-filter cat -- --all
# Langkah 3: Force push ke remote
git push origin --force --all
# Langkah 4: Bersihkan cache GitHub (hubungi juga GitHub Support)
Kasus 2: DROP TABLE Dijalankan di DB Produksi
Apa yang Terjadi
“Tabel ini sudah tidak dipakai, tolong hapus.” Claude Code menghasilkan dan menjalankan DROP TABLE old_users;. Masalahnya: itu terhubung ke DATABASE_URL produksi. Backup terbaru sudah tiga hari yang lalu. Data tiga hari lenyap.
Penyebab
.envyang sama digunakan bersama antara development dan production- Claude Code tidak dapat membedakan antara lingkungan
- Pengguna dalam mode
asktetapi mengklik “OK” secara refleks
Kode Pencegahan
1. Pisahkan file .env sepenuhnya per lingkungan
.env.development # ← pengembangan lokal, DB dummy
.env.staging # ← staging, salinan produksi
.env.production # ← produksi, dikelola manual, jangan pernah dibagikan
2. Sematkan pemeriksaan lingkungan dalam skrip
// scripts/db-migrate.mjs
const env = process.env.APP_ENV ?? "development";
const dbUrl = process.env.DATABASE_URL ?? "";
if (env === "production") {
const readline = require("readline").createInterface({
input: process.stdin, output: process.stdout
});
await new Promise((resolve) => {
readline.question(
`⚠️ Menghubungkan ke DB produksi (${dbUrl.split("@")[1]}).\nApakah Anda yakin ingin melanjutkan? (ketik yes): `,
(answer) => {
readline.close();
if (answer !== "yes") { console.log("Dibatalkan."); process.exit(0); }
resolve(undefined);
}
);
});
}
3. Larang operasi produksi di CLAUDE.md
## 🚨 Pembatasan Lingkungan Produksi
Jika DATABASE_URL mengandung `prod`, `production`, atau `live`:
- Jangan pernah menjalankan DROP / TRUNCATE / DELETE (tanpa klausa WHERE)
- Selalu dapatkan konfirmasi pengguna sebelum migrasi
- Tampilkan perintah backup sebelum operasi destruktif apa pun
Kasus 3: File Penting Terhapus dengan rm -rf
Apa yang Terjadi
“Bersihkan direktori build/” — typo pada path menghasilkan rm -rf ./, menghapus seluruh proyek. File di luar git (konfigurasi lokal, kode eksperimen yang belum di-commit) hilang selamanya.
Penyebab
rm -rfadalah salah satu perintah paling berbahaya bagi Claude Code- Tidak ada tanda kutip ganda di sekitar path → perilaku buruk dengan path yang mengandung spasi
- Pengguna menyetujui dengan ceroboh
Kode Pencegahan
// .claude/settings.json
{
"permissions": {
"deny": [
"Bash(rm -rf /)",
"Bash(rm -rf ~*)",
"Bash(rm -rf .*)"
],
"ask": [
"Bash(rm -rf*)"
]
}
}
Hook untuk menampilkan apa yang akan dihapus sebelum dieksekusi:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(rm*)",
"hooks": [{
"type": "command",
"command": "echo '⚠️ Perintah hapus terdeteksi. Menjalankan dalam 5 detik. Ctrl+C untuk membatalkan.' && sleep 5"
}]
}
]
}
}
Kasus 4: API Key Ditulis Langsung di Prompt dan Diteruskan ke Subagent
Apa yang Terjadi
“Tolong posting ke Qiita menggunakan QIITA_TOKEN=abc123def456” — ditulis langsung di prompt dan didelegasikan ke subagent. Subagent dapat menulis konten ke log dan memori, dan token akhirnya tersimpan dalam file log di bawah .claude/.
Penyebab
- Prompt dipertahankan sebagai riwayat percakapan
- Prompt subagent juga tercatat dengan cara yang sama
- Bahkan di lingkungan lokal, proses lain atau backup dapat mengekspos rahasia
Kode Pencegahan
Jangan pernah menulis rahasia di prompt — teruskan melalui variabel lingkungan
# ❌ Berbahaya
claude -p "Gunakan QIITA_TOKEN=abc123 untuk menjalankan qiita-publish.mjs"
# ✅ Aman: skrip membaca dari process.env
# Tulis QIITA_TOKEN=abc123 di .env, lalu
claude -p "Jalankan scripts/qiita-publish.mjs (token dibaca otomatis dari .env)"
Prinsip yang sama untuk instruksi subagent
// ❌ Berbahaya
Agent({ prompt: `Gunakan API key ${process.env.SECRET_KEY} untuk...` });
// ✅ Aman: hanya berikan nama key, skrip membaca nilainya
Agent({ prompt: "Gunakan variabel lingkungan SECRET_KEY untuk..." });
Kasus 5: Loop Retry API Tanpa Henti Meledakkan Tagihan
Apa yang Terjadi
“Coba ulang otomatis jika ada error” — skrip dengan penanganan error dihasilkan. Ketika sebuah error tidak dapat diselesaikan, retry tidak pernah berhenti: 3.000 panggilan API Anthropic dalam satu jam menghasilkan tagihan $200.
Penyebab
- Tidak ada batas retry yang ditetapkan
- Tidak ada exponential backoff — loop tanpa henti dengan interval 1 detik
- Tidak ada alert tagihan yang dikonfigurasi
Kode Pencegahan
// utils/retry.ts — utilitas retry yang aman
export async function withRetry<T>(
fn: () => Promise<T>,
options = { maxAttempts: 3, baseDelayMs: 1000, maxDelayMs: 30000 }
): Promise<T> {
let lastError: Error;
for (let attempt = 1; attempt <= options.maxAttempts; attempt++) {
try {
return await fn();
} catch (err) {
lastError = err as Error;
if (attempt === options.maxAttempts) break;
// Exponential backoff + jitter
const delay = Math.min(
options.baseDelayMs * Math.pow(2, attempt - 1) + Math.random() * 1000,
options.maxDelayMs
);
console.warn(`Attempt ${attempt}/${options.maxAttempts} failed: ${err.message}`);
console.warn(`Retrying in ${Math.round(delay / 1000)}s...`);
await new Promise((r) => setTimeout(r, delay));
}
}
throw new Error(`Gagal setelah ${options.maxAttempts} percobaan: ${lastError!.message}`);
}
Tentukan di CLAUDE.md:
## Aturan Wajib untuk Panggilan API
- Maksimal 3 retry
- Selalu implementasikan exponential backoff (1s → 2s → 4s)
- Jangan pernah membuat loop tanpa henti: while(true) + panggilan API dilarang
Kasus 6: git push --force Menghapus Commit Rekan Kerja
Apa yang Terjadi
“Timpa remote dengan kondisi lokal” — git push --force dijalankan. Tiga commit yang baru saja di-push oleh anggota tim hilang. Anggota tersebut juga tidak memiliki salinan lokal dari perubahan itu — kode hilang selamanya.
Penyebab
--forcecenderung dijalankan tanpa memahami bahayanya- Claude Code dengan patuh menjalankan instruksi “timpa remote”
- Developer tidak mengetahui alternatif yang lebih aman
git push --force-with-lease
Kode Pencegahan
// .claude/settings.json
{
"permissions": {
"deny": [
"Bash(git push --force *master*)",
"Bash(git push --force *main*)",
"Bash(git push -f *master*)",
"Bash(git push -f *main*)"
]
}
}
Tentukan alternatif aman di CLAUDE.md:
## Aturan Git yang Aman
- `git push --force` **dilarang**
- Gunakan `git push --force-with-lease` sebagai gantinya
(ditolak otomatis jika orang lain telah push perubahan)
- Selalu dapatkan konfirmasi pengguna sebelum push langsung ke main/master
Kasus 7: Service Account dengan Hak Berlebihan Mengakses Semua Sumber Daya
Apa yang Terjadi
“Gunakan kunci service account GCP ini untuk mengoperasikan Cloud Storage.” Service account memiliki izin Owner. Claude Code terhubung tidak hanya ke Cloud Storage tetapi juga ke BigQuery, Cloud SQL, dan cluster GKE “untuk menginvestigasi” — menghasilkan biaya yang tidak terduga.
Penyebab
- Service account memiliki izin berlebihan (pelanggaran prinsip hak minimum)
- Claude Code memiliki kecenderungan agresif untuk menggunakan alat yang tersedia
- Bahkan “untuk menginvestigasi” terdengar seperti alasan yang sah untuk akses luas
Kode Pencegahan
Buat service account dengan hak minimum:
# ❌ Hindari: izin Owner
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:[email protected]" \
--role="roles/owner"
# ✅ Hanya izin minimum yang diperlukan
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:[email protected]" \
--role="roles/storage.objectAdmin"
# ← Hanya baca/tulis ke Cloud Storage
Definisikan cakupan akses secara eksplisit di CLAUDE.md:
## Pembatasan Akses GCP
Izin untuk service account yang digunakan dalam proyek ini:
- Cloud Storage: Baca/Tulis OK (bucket: my-project-assets saja)
- BigQuery: Dilarang
- Cloud SQL: Dilarang
- Sumber daya GCP lainnya: Dilarang
Tolak instruksi apa pun yang mencoba mengakses sumber daya di luar izin ini.
Daftar Periksa Komprehensif untuk Mencegah Insiden
Daftar periksa akhir yang disuling dari pola umum di ketujuh kasus.
### Pengaturan yang Harus Diterapkan Hari Ini (30 menit)
- [ ] Tambahkan pola .env ke .gitignore
- [ ] Tambahkan daftar deny ke .claude/settings.json (rm -rf, git push --force, DROP TABLE)
- [ ] Dokumentasikan pembatasan di CLAUDE.md
### Pemeriksaan Mingguan
- [ ] Tinjau git log untuk commit file yang tidak disengaja
- [ ] Verifikasi .env dikecualikan oleh .gitignore: `git check-ignore -v .env`
- [ ] Periksa tenggat waktu rotasi API key
### Respons Pertama terhadap Insiden
1. Segera cabut dan rotasi API key yang terpengaruh
2. Hapus dari riwayat git (filter-branch atau BFG)
3. Tinjau log akses untuk menentukan cakupan pelanggaran
4. Laporkan situasi kepada pemangku kepentingan
Ringkasan
Insiden Claude Code jarang disebabkan oleh “AI yang mengamuk” — hampir semua muncul dari manusia yang menunda konfigurasi keamanan.
| Kasus | Penyebab Utama | Pencegahan |
|---|---|---|
| Kebocoran .env | Tidak ada gitignore | Script init + Hook |
| Penghapusan DB produksi | Tidak ada pemisahan lingkungan | .env terpisah + alur konfirmasi |
| Kecelakaan rm -rf | Tidak ada daftar deny | Konfigurasi settings.json |
| Kebocoran key | Ditulis di prompt | Standarkan ke env vars |
| Ledakan tagihan | Tidak ada batas retry | Utilitas withRetry |
| Force push | Tidak ada pengaturan larangan | deny + force-with-lease |
| Akses hak berlebihan | Pelanggaran hak minimum | Batasi peran IAM |
Langkah pertama Anda hari ini: Menambahkan "deny": ["Bash(rm -rf*)"] ke .claude/settings.json saja sudah dapat mencegah salah satu kecelakaan paling destruktif yang mungkin terjadi.
Artikel Terkait
- Panduan Lengkap Praktik Terbaik Keamanan Claude Code
- Panduan Lengkap Izin Claude Code
- Praktik Terbaik CLAUDE.md
Referensi
Tingkatkan alur kerja Claude Code kamu
50 template prompt yang sudah teruji, siap copy-paste ke Claude Code sekarang juga.
PDF Gratis: Cheatsheet Claude Code dalam 5 Menit
Cukup masukkan emailmu dan kami akan langsung mengirim cheatsheet PDF A4 satu halaman.
Kami menjaga data pribadimu dengan aman dan tidak pernah mengirim spam.
Tentang Penulis
Masa
Engineer yang aktif menggunakan Claude Code. Mengelola claudecode-lab.com, media teknologi 10 bahasa dengan lebih dari 2.000 halaman.
Artikel Terkait
Panduan Lengkap Keamanan Claude Code: Kunci API, Izin, dan Perlindungan Produksi
Panduan keamanan praktis untuk menggunakan Claude Code dengan aman. Dari manajemen kunci API hingga pengaturan izin, otomasi berbasis Hooks, dan perlindungan lingkungan produksi — dengan contoh kode yang berfungsi.
Panduan Lengkap Izin Claude Code | settings.json, Hooks, dan Allowlist Dijelaskan
Penjelasan lengkap pengaturan izin Claude Code. Pelajari penggunaan allow/deny/ask, otomatisasi dengan Hooks, settings.json per lingkungan, dan pola praktis — dengan kode yang berfungsi.
Panduan Lengkap Harness Engineering: Membangun Agen AI ala Claude Code
Prompt saja tidak cukup untuk menjinakkan LLM. Pelajari cara merangkai tool, konteks, dan control loop menjadi harness, lengkap dengan kode yang bisa dijalankan dan arsitektur Claude Code sebagai panduan.