Skenario paling dingin di dunia version control dimulai sederhana: berkas .env berisi koneksi database dan API key ikut ter-commit, ketemu seminggu kemudian. Refleks pertama hampir semua orang — hapus berkasnya, commit, selesai — dan refleks itu salah total. Commit bukan tempat penyimpanan terkini, melainkan mesin waktu: setiap commit adalah snapshot utuh yang tidak pernah diubah oleh commit setelahnya. Chapter ini membuktikan dengan perintah nyata bahwa secret yang “dihapus” tetap terbaca dari riwayat, menyebar ke setiap clone, dan — bila repo dipublikasikan — dipindai platform secara otomatis. Respons insidennya dibahas di akhir, dan pembersihan riwayatnya menunggu di Menghapus Secret dari Riwayat .

Demo: Berkas Dihapus, Secret Tetap Ada #

Sandbox menyiapkan repository toko-buku dengan tiga commit: proyek dimulai, konfigurasi lingkungan ditambahkan, lalu berkasnya dihapus:

bash
git log --oneline

Output yang Dihasilkan:

text
0df07cd Hapus berkas rahasia dari repository
f463b04 Tambah konfigurasi lingkungan
7871a7a Commit awal proyek

Hash di mesin pembaca berbeda, urutan dan pesannya yang stabil. Posisi terakhir memang bersih — .env sudah tidak ada:

bash
git show HEAD:.env

Output yang Dihasilkan:

text
fatal: path '.env' does not exist in 'HEAD'

Namun commit f463b04 adalah snapshot lengkap saat .env masih hidup, dan snapshot itu tidak ikut terhapus:

bash
git show f463b04:.env

Output yang Dihasilkan:

text
DATABASE_URL=postgres://budi:[email protected]/toko
API_KEY=sk-live-YOUR_API_KEY

Inilah bukti terkuat bahwa “hapus berkasnya” tidak pernah menghapus secret: git show <hash>:.env membuka isi berkas tepat seperti saat commit itu dibuat. Perintah git rm pada commit ketiga hanya menambahkan snapshot baru yang tidak memuat .env — snapshot lama tetap utuh di object database, terjangkau satu hash jauhnya.

Riwayat Menyebar ke Setiap Clone #

Sifat terdistribusi Git memperparah keadaan. Satu perintah git clone menyalin seluruh object database — termasuk snapshot ber-secret. Sandbox membuktikannya dengan meng-clone repository di atas ke direktori klon-teman, lalu membaca berkas yang sama dari clone tersebut:

bash
cd klon-teman
git show f463b04:.env

Output yang Dihasilkan:

text
DATABASE_URL=postgres://budi:[email protected]/toko
API_KEY=sk-live-YOUR_API_KEY

Setiap pemilik clone — kolega, server CI, fork di akun orang lain — memegang salinan yang identik. Membersihkan riwayat di repository pusat tidak menyentuh clone-clone itu; secret tetap terbaca dari laptop kolega meskipun repository pusat sudah steril. Konsekuensinya lugas: satu-satunya tindakan yang menutup insiden bagi semua pemegang salinan adalah merotasi kredensialnya, bukan membersihkan berkasnya.

Melacak Jejak: log –all –source #

Sebelum membersihkan, ketahui dulu jejaknya. Opsi --all memeriksa seluruh ref (semua branch, tag, remote-tracking), dan --source menampilkan ref mana yang membawa tiap commit:

bash
git log --all --source --oneline -- .env

Output yang Dihasilkan:

text
0df07cd	refs/heads/main Hapus berkas rahasia dari repository
f463b04	refs/heads/main Tambah konfigurasi lingkungan

Dua commit menyentuh .env: yang memasukkannya dan yang menghapusnya — keduanya di main. Pada repository nyata, keluaran ini sering lebih panjang: branch lama yang belum terhapus, tag rilis, bahkan commit yang hanya hidup di remote-tracking branch pun ikut terdaftar. Daftar ini adalah peta kerja untuk Menghapus Secret dari Riwayat : pembersihan harus menyentuh setiap ref di daftar itu, bukan hanya main.

Platform Memindai Secret #

Untuk repository yang berada di platform, ada penjaga ketiga yang bekerja otomatis: secret scanning. GitHub memindai isi repository untuk pola kredensial yang dikenali — format token GitHub, kunci AWS, string koneksi database, dan daftar panjang lainnya — dalam dua arah: push protection menolak push yang berisi secret sebelum ia masuk, dan pemindaian historis mencari secret di repo publik yang sudah ada. Bila token GitHub sendiri terdeteksi, platform tidak hanya memberi laporan: token dinonaktifkan otomatis dan pemiliknya dikabarkan. GitLab menempatkan fitur setara lewat secret push protection. Perilaku platform ini terdokumentasi di dokumentasi GitHub tentang secret scanning .

Dua catatan penting menjaga ekspektasi tetap jujur. Pemindaian otomatis hanya menjamin terhadap pola yang dikenali — string rahasia internal perusahaan tidak dikenali polanya dan lolos begitu saja. Dan pada repository privat, pemindaian menyeluruh umumnya adalah fitur berbayar atau perlu diaktifkan organisasi — jangan berasumsi repo privat sudah terlindungi.

Respons Insiden: Rotasi Dulu, Bersih-bersih Kemudian #

Saat secret ter-commit diketahui, urutan tindakan menentukan besar kerusakan. Empat langkah ini disusun berdasarkan prioritas:

LangkahTindakanAlasannya
1. Rotasicabut/ganti kredensial di platform penyedianya sekarangclone lama memegang secret selamanya; hanya rotasi yang menutup aksesnya
2. Evaluasigit log --all --source -- <berkas> untuk memetakan sebaranpembersihan harus menyentuh semua ref yang tercatat
3. Bersihkantulis ulang riwayat dengan alat yang sesuaimencegah clone baru mewarisi secret
4. Auditperiksa log aktivitas platformmencari tanda token dipakai pihak lain selama bocor

Urutan langkah 1 sebelum 3 bukan selera: pembersihan riwayat butuh waktu — koordinasi tim, force-push, re-clone — dan selama waktu itu secret tetap hidup di clone-clone lama. Rotasi memutus aksesnya seketika tanpa menunggu pembersihan tuntas.

Dengan secret sudah dirotasi, pekerjaan berikutnya menjadikan repository itu sendiri bersih — tiga jalur pembersihan, dari yang ringan untuk commit terakhir hingga menulis ulang seluruh riwayat, menunggu di Menghapus Secret dari Riwayat .