Tidak suka iklan? Pergi Bebas Iklan Hari ini

File .env — 6 Kesalahan yang Menyebabkan Kunci Anda Tersimpan di GitHub

Diperbarui pada

Kebanyakan kebocoran file .env bukan karena para hacker — melainkan karena para pengembang yang mengunggah file sebelum aturan .gitignore diatur, mengirimkan file .env.example dengan nilai aktual, atau membiarkan kerangka kerja secara diam-diam mengintegrasikan rahasia server ke dalam JavaScript klien. Berikut ini adalah 6 kesalahan yang sebenarnya terjadi.

Sebagian besar kebocoran .env bukan dari penyerang — mereka dari pengembang yang mengunggah file sebelum .gitignore diatur, mengirimkan .env.example dengan nilai nyata, atau membiarkan framework secara diam-diam mengikat rahasia server ke dalam JavaScript klien. Berikut adalah 6 kesalahan yang sebenarnya terjadi.
IKLAN · HAPUS?

Laporan tentang Penyebaran Rahasia GitGuardian tahun 2023 menemukan lebih dari 12 juta rahasia yang diserahkan ke repositori GitHub publik. Sebagian besar tidak dicuri — mereka diunggah oleh pengembang yang benar-benar berpikir mereka telah menangani hal tersebut. Ini adalah pola yang bertanggung jawab.

1. Menambahkan .gitignore setelah komit pertama

.gitignore dipindahkan. Jika file sudah ada di sejarah Git, menambahkannya ke tidak berpengaruh. Git tetap mengendalikannya dan akan tetap mengonfirmasi perubahan terhadap file tersebut. file dari proses penyimpanan. Sekali suatu file diikuti — bahkan secara singkat — maka ia masuk ke sejarah git. Jika Anda membuat .env, menjalankan git add . && git commit, lalu menambahkan .env ke .gitignore setelahnya, file tersebut tetap ada di setiap komit sebelum perubahan tersebut.

Periksa apakah sudah ada di sejarah:

git log --all -- .env

Jika hasilnya adalah komit, maka rahasia tersebut ada di sejarah. Rotasi kredensial terlebih dahulu. Lalu hapus file tersebut dari sejarah menggunakan git-filter-repo (pengganti yang direkomendasikan untuk git filter-branch):

pip install git-filter-repo
git filter-repo --path .env --invert-paths

Lakukan force-push ke semua remote dan beri tahu rekan kerja untuk mengklon ulang. Komit-komit tersebut tetap ada di setiap klon yang dibuat sebelum penghapusan — termasuk sistem CI otomatis yang melakukan pengekstensi repositori tersebut.

2. Menyalin .env ke .env.example tanpa menghapus nilai-nilai

Alur standar: buat .env dengan nilai nyata, lalu salin ke .env.example untuk menunjukkan rekan kerja apa saja kunci yang dibutuhkan proyek tersebut. Salinan inilah yang menjadi masalahnya.

cp .env .env.example menggandakan semua — kunci dan nilai. Dan .env.example seharusnya disimpan. Itulah tujuan utamanya. Nilai nyata di .env.example dimasukkan secara sengaja ke dalam repositori.

❌ Apa yang akhirnya masuk ke git:

DATABASE_URL=postgres://admin:supersecretpassword@prod-db.example.com/appdb
STRIPE_SECRET_KEY=sk_live_51AbcDefGhiJklMnopQrstUvwx...
JWT_SECRET=my-actual-production-jwt-secret

✅ Apa yang .env.example seharusnya terlihat:

DATABASE_URL=postgres://user:password@localhost:5432/appdb
STRIPE_SECRET_KEY=sk_live_YOUR_KEY_HERE
JWT_SECRET=generate-a-random-secret-min-32-chars

Membuat .env.example dengan nilai placeholder terlebih dahulu, komitkan, lalu salin ke .env dan isi nilai nyata — bukan sebaliknya.

3. Mencatat process.env dalam penangulang kesalahan

Yang satu ini dimulai sebagai 'debug cepat' saat insiden terjadi dan tidak pernah dihapus. Atau ia berada di middleware kesalahan umum yang tampaknya tidak berbahaya.

// Classic debug line that makes it to production
console.log('Starting with config:', process.env);

// Generic error handler that dumps everything
app.use((err, req, res, next) => {
  logger.error({ config: process.env, error: err.message });
  res.status(500).json({ error: 'Internal server error' });
});

process.env di runtime mencakup setiap variabel yang dimuat oleh dotenv, ditambah variabel sistem. Menyampaikan objek lengkap ke logger berarti data tersebut masuk ke aggregator log Anda, layanan pelacakan kesalahan (Sentry, Datadog, Rollbar), dan mungkin ke email atau webhook pemberitahuan kesalahan. Banyak layanan ini mengalir ke penyimpanan pihak ketiga dengan kontrol akses mereka sendiri.

Catat hanya nilai-nilai yang diperlukan untuk diagnosis:

logger.error({
  nodeEnv: process.env.NODE_ENV,
  appVersion: process.env.APP_VERSION,
  error: err.message,
  stack: err.stack
});

4. Menyisipkan rahasia ke lapisan gambar Docker

Dua pola yang secara permanen menyisipkan rahasia ke sejarah gambar Docker:

# Pattern 1: COPY bakes the entire .env into a layer
COPY .env .

# Pattern 2: ARG/ENV burns values into build metadata
ARG DATABASE_URL
ENV DATABASE_URL=$DATABASE_URL

Meskipun Anda menghapus file di lapisan berikutnya (RUN rm .env), nilai tersebut tetap dapat dibaca dalam sejarah gambar. Siapa pun yang memiliki akses pull ke gambar dapat menjalankan:

docker history --no-trunc your-image:tag

dan memulihkan nilai ARG yang digunakan saat pembangunan. Docker BuildKit rahasia adalah alat yang tepat — ia menempatkan rahasia selama pembangunan tanpa menulisnya ke lapisan apa pun:

# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=db_url     DATABASE_URL=$(cat /run/secrets/db_url) ./setup.sh

Untuk konfigurasi saat berjalan, injeksi variabel lingkungan saat memulai kontainer melalui docker run -e atau environment: dalam Docker Compose yang merujuk ke variabel lingkungan host — tidak pernah nilai yang dihardcode, tidak pernah COPY‘dari file rahasia.

5. Menggunakan placeholder rahasia lemah yang dikirim ke produksi

JWT_SECRET=secret, SESSION_SECRET=keyboard cat, APP_KEY=changeme, ENCRYPTION_KEY=1234567890abcdef. Ini dimulai sebagai placeholder pengembangan dan kadang-kadang tidak pernah diganti. Penyerang yang melakukan brute-force pada tanda tangan JWT secara aktif mencoba string ini — mereka ada dalam daftar kata karena muncul di pencarian GitHub.

Sebuah JWT yang ditandatangani dengan HS256 dan rahasia lemah dapat ditebak secara offline dengan alat seperti c-jwt-cracker. Satu token yang berhasil ditangkap cukup untuk melakukan brute-force pada rahasia dan membuat token sembarang.

Rahasia yang benar harus acak secara kriptografi, minimal 32 byte. Buatlah mereka sebelum Anda membutuhkannya — Generator Rahasia Lingkungan di IO Tools akan menghasilkan nilai yang acak secara tepat untuk rahasia umum .env (kunci JWT, rahasia sesi, kunci API) tanpa memerlukan pengaturan apa pun. Tetapkan sejak awal; jangan gunakan placeholder dan rencanakan untuk 'memperbaikinya sebelum produksi.'

6. Konvensi variabel lingkungan framework yang mengungkapkan rahasia ke klien

Beberapa framework populer menggunakan prefiks nama variabel untuk menentukan visibilitas antara klien dan server. Salahnya dalam hal ini menyebabkan rahasia masuk ke bundle JavaScript ke setiap browser yang memuat aplikasi Anda — dalam bentuk teks murni.

  • Next.js: Setiap direktori bernama NEXT_PUBLIC_-prefiks variabel diikat ke sisi klien. Namun rahasia server bocor saat dilewatkan melalui getServerSideProps props — setiap nilai yang dikembalikan dalam props dikonversi ke HTML halaman dan dapat dibaca dari sumber.
  • Vite: Variabel yang prefiks VITE_ dikompilasi ke dalam JavaScript klien. Menggunakan VITE_DATABASE_URL “untuk kenyamanan” adalah kesalahan yang sebenarnya dilakukan oleh pengembang.
  • Create React App: Semua REACT_APP_ variabel akhirnya masuk ke bundle klien, tanpa pengecualian. Tidak ada runtime CRA di sisi server — semua yang memuat akan masuk ke browser.

Verifikasi setelah pembangunan dengan mencari nilai rahasia yang dikenal di direktori output:

grep -r "sk_live_" ./dist
grep -r "sk_live_" ./.next/static

Jika ada nilai yang cocok, maka rahasia tersebut ada di setiap tab browser. Rotasi segera dan audit apa saja yang dibundel.

Satu kebiasaan yang perlu dibangun sejak awal

Sebelum membuat file apa pun yang akan menyimpan rahasia, atur .gitignore terlebih dahulu — bukan sebagai hal yang terlambat. Komit pertama di repositori baru harus .gitignore dan .env.example dengan nilai placeholder. Akan menghasilkan file ignore lengkap, sesuai dengan framework, dalam waktu kurang dari satu menit. .gitignore Generator Keenam kesalahan di atas semua dapat dicegah sebelum kode ditulis. Rotasi adalah satu-satunya solusi setelah rahasia terbuka — dan itu berarti rotasi di mana-mana: penyedia layanan, setiap lingkungan yang memiliki salinan, dan setiap sistem yang mungkin menyimpan nilai tersebut di log.

.env Files — 6 Kesalahan yang Menyebabkan Rahasia Anda Masuk ke GitHub 2

Ingin bebas iklan? Bebas Iklan Hari Ini

Instal Ekstensi Kami

Tambahkan alat IO ke browser favorit Anda untuk akses instan dan pencarian lebih cepat

Ke Ekstensi Chrome Ke Ekstensi Tepi Ke Ekstensi Firefox Ke Ekstensi Opera

Papan Skor Telah Tiba!

Papan Skor adalah cara yang menyenangkan untuk melacak permainan Anda, semua data disimpan di browser Anda. Lebih banyak fitur akan segera hadir!

IKLAN · HAPUS?
IKLAN · HAPUS?
IKLAN · HAPUS?

Pojok Berita dengan Sorotan Teknologi

Terlibat

Bantu kami untuk terus menyediakan alat gratis yang berharga

Belikan aku kopi
IKLAN · HAPUS?