Sejauh ini kita mengamankan kode yang KITA tulis sendiri. Tapi task-tracker-api juga bergantung pada puluhan package pihak ketiga (FastAPI, SQLModel, bcrypt, dst.) dan image dasar Docker yang tidak kita tulis sendiri. Kerentanan di sana sama berbahayanya — bahkan sering lebih berbahaya, karena kita tidak selalu sadar sedang memakainya. Ini yang disebut supply chain security.
Kenapa Dependency Bisa Jadi Celah
Setiap pip install menarik kode dari orang lain ke dalam aplikasi kita, dengan level kepercayaan yang sama seperti kode yang kita tulis sendiri. Kalau salah satu dependency (atau dependency-nya dependency, disebut transitive dependency) punya kerentanan yang sudah diketahui publik (tercatat di database CVE), aplikasi kita otomatis ikut rentan — walaupun kita sendiri tidak pernah menulis baris kode yang bermasalah.
Scanning Dependency dengan pip-audit
pip-audit adalah tool resmi dari Python Packaging Authority yang mengecek requirements.txt terhadap database kerentanan yang diketahui:
pip install pip-audit
pip-audit -r requirements.txt
No known vulnerabilities found
Hasil bersih di titik ini — tapi ini BUKAN pemeriksaan sekali jalan lalu selesai. Kerentanan baru ditemukan di package yang sudah ada terus-menerus (kadang di package yang sudah bertahun-tahun dianggap aman). Praktik yang benar: jalankan pip-audit secara rutin — idealnya otomatis di setiap pipeline CI (persis konsep yang dibahas di CI/CD for Beginners, tinggal ditambahkan sebagai satu step baru di job test).
Kalau pip-audit menemukan kerentanan, biasanya solusinya sesederhana update ke versi yang sudah memperbaikinya:
pip-audit -r requirements.txt --fix
Tapi selalu jalankan test suite lagi setelah update — versi baru kadang membawa perubahan API yang bisa merusak kode yang sudah ada (breaking change).
Container Hardening — Jangan Jalankan sebagai Root
Secara default, container Docker berjalan sebagai user root di dalamnya — kalau ada yang berhasil mengeksploitasi celah di aplikasi kita untuk mengeksekusi kode arbitrer, root di dalam container itu punya keleluasaan jauh lebih besar (menulis ke seluruh filesystem container, dan di beberapa skenario misconfiguration, bahkan "kabur" ke luar container).
Dockerfile kita secara eksplisit membuat dan beralih ke user biasa:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app ./app
# Jangan jalankan sebagai root
RUN useradd --create-home --shell /usr/sbin/nologin appuser
USER appuser
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Buktikan langsung:
docker build -t security-demo-app .
docker run --rm security-demo-app whoami
appuser
Bukan root. Ini prinsip least privilege — proses apa pun sebaiknya berjalan dengan hak akses SEMINIMAL yang dibutuhkannya untuk bekerja, bukan yang paling leluasa "supaya aman dari error permission". Aplikasi kita tidak pernah butuh menginstall software baru atau memodifikasi file sistem saat runtime — jadi tidak ada alasan dia perlu jalan sebagai root.
Kebiasaan Baik Lain untuk Image Docker
Beberapa praktik tambahan yang sudah — atau sebaiknya — diterapkan:
python:3.11-slim, bukan python:3.11 biasa) — semakin sedikit software terpasang di image, semakin kecil permukaan serangannya (attack surface). Setiap tool tambahan yang tidak dipakai aplikasi adalah potensi celah yang tidak perlu ada.Dockerfile kita cuma COPY app ./app, bukan seluruh direktori proyek. File seperti .env, tests/, atau .git/ tidak pernah masuk ke image production.python:3.11-slim sebaiknya di-pin ke tag yang lebih spesifik (misalnya python:3.11.9-slim) di lingkungan production, supaya build selalu deterministik dan tidak diam-diam berubah begitu ada rilis baru yang mungkin membawa masalah.Rangkuman
pip-audit mengecek dependency terhadap database kerentanan yang diketahui — jalankan rutin, idealnya otomatis di CI.