Least privilege và image supply chain
Secure container không chỉ là dùng image nhỏ. Phải bảo vệ đồng thời build inputs, artifact identity, registry/CI và runtime privileges; mỗi control giảm một nhóm rủi ro khác nhau và không control nào tự chứng minh image “an toàn tuyệt đối”.
1. Security boundary và least privilege
Container dùng chung kernel với host, nên namespace/cgroup giúp giảm phạm vi nhưng không biến root trong container thành “vô hại”. Quyền điều khiển Docker daemon hoặc Docker socket có sức mạnh rất lớn vì có thể tạo container với host mounts và nhiều quyền khác. Chỉ cấp quyền daemon cho principal tin cậy; không mount Docker socket vào workload thông thường.
Ưu tiên chạy workload bằng fixed non-root UID/GID, root filesystem read-only, writable path được khai báo rõ, drop Linux capabilities, bật no-new-privileges, giữ seccomp/LSM policy, và đặt PID/memory/CPU limits. Tránh --privileged, host namespace và writable host mounts trừ khi threat model thật sự yêu cầu và đã có compensating controls.
2. Runtime hardening
| Control | Mục tiêu | Trade-off / lưu ý |
|---|---|---|
| Non-root UID/GID | Giảm impact khi process bị compromise. | App phải có permission đúng trên mount/path cần ghi; fixed UID giúp dự đoán ownership. |
--read-only + explicit writable mounts | Giảm persistence/tampering trong rootfs. | Cần tmpfs hoặc volume cho /tmp, cache, uploads, PID/socket files nếu app cần. |
--cap-drop=ALL | Giảm quyền kernel không cần thiết. | Chỉ add lại capability thật sự cần; test behavior thay vì add rộng. |
no-new-privileges | Ngăn process đạt thêm privilege qua exec/setuid. | Có thể làm một số binary/helper cũ không chạy. |
| Default seccomp + LSM | Giảm syscall/action có thể sử dụng khi bị exploit. | Custom profile quá chặt có thể gây lỗi khó chẩn đoán; không tắt default profile chỉ để “cho chạy”. |
| PID/memory/CPU limits | Giới hạn blast radius của fork bomb, memory leak hoặc runaway CPU. | Limit quá thấp tạo self-inflicted outage; phải đo peak và có headroom. |
# Ví dụ baseline; điều chỉnh port/mount/limit theo workload thật.
docker run --rm \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=64m \
--cap-drop=ALL \
--security-opt no-new-privileges=true \
--pids-limit 200 \
--memory 512m \
--cpus 1 \
registry.example.com/payments@sha256:<digest>
3. Image hygiene
Dùng minimal, trusted base image; loại bỏ compiler/package manager/debug tool không cần ở runtime; dùng multi-stage build; scan cả OS packages lẫn application dependencies. Pin digest khi cần reproducibility/assurance cao vì tag là mutable pointer, không phải bằng chứng content identity.
Pin digest cũng có trade-off: image không tự nhận security update mới. Vì vậy cần bot/process phát hiện base digest mới, rebuild định kỳ hoặc theo CVE, test rồi promote digest mới. “Image nhỏ” giảm attack surface tiềm năng nhưng không thay thế provenance, vulnerability management hay runtime hardening.
Build secret đúng cách
Không dùng ARG hoặc ENV để đưa credential vào build vì chúng có thể tồn tại trong image metadata/layers. Docker BuildKit secret mount chỉ expose secret trong build step thay vì bake secret vào image.
# CLI
docker build --secret id=npm_token,src=.npm-token -t app:build .
# Dockerfile
RUN --mount=type=secret,id=npm_token \
NPM_TOKEN="$(cat /run/secrets/npm_token)" npm ci
4. Supply chain: identity, provenance và promotion
Lock dependencies, protect source control/CI builder/registry, tạo SBOM và provenance, ký/verify artifact theo trust policy, và promote cùng một digest giữa environments. Rebuild riêng cho staging và production tạo hai artifact khác nhau dù source giống nhau.
# Build + push với SBOM và provenance attestations
docker buildx build \
--sbom=true \
--provenance=true \
-t registry.example.com/app:2026-09-12 \
--push .
# Deploy bằng immutable digest thay vì tin vào tag
registry.example.com/app@sha256:<verified-digest>
SBOM trả lời “artifact chứa component nào”; provenance trả lời “artifact được build như thế nào/từ inputs nào” theo mức metadata được tạo. Signature/attestation giúp bind identity và statement với artifact, nhưng verifier vẫn phải có trust policy: signer/issuer nào được chấp nhận, source repo/ref nào hợp lệ, builder nào được tin, và policy nào phải pass trước deploy.
SLSA là framework tăng dần assurance cho software supply chain. Với SLSA v1.2 hiện hành, hãy chọn track/level phù hợp thay vì nói chung chung “SLSA compliant”; scope guarantee phải gắn với control thực tế của source/build platform và verification policy.
5. Threats, failure windows và operational signals
| Threat / failure | Failure window | Signal nên theo dõi | Containment đầu tiên |
|---|---|---|---|
| Malicious/outdated base hoặc dependency | Từ lúc dependency bị compromise/CVE xuất hiện đến khi image mới được rebuild và deploy. | New critical/high CVE, base digest drift, unexpected package/SBOM delta. | Block promotion theo policy; rebuild từ approved base/dependency; expire exception có owner. |
| Registry credential theft / tag overwrite | Từ credential compromise đến revoke; tag mutable có thể trỏ sang digest khác. | Push từ principal/IP bất thường, tag digest changed, failed signature/provenance verification. | Revoke/rotate credential, quarantine digest, deploy only verified digest. |
| CI/builder poisoning | Có thể kéo dài qua nhiều release cho tới khi provenance/build behavior được điều tra. | Unexpected builder identity, changed workflow, provenance mismatch, anomalous outbound access. | Disable compromised runner/identity, rotate secrets, rebuild trên trusted builder. |
| Exposed Docker API/socket | Attack có thể thành host-level impact rất nhanh. | Unexpected containers, privileged flags, host mounts, daemon API access. | Isolate host, revoke access, stop unauthorized workloads, preserve audit evidence. |
| Container escape / excessive privilege | Từ exploit đến detection; blast radius tăng mạnh nếu privileged/host mounts. | Unexpected syscalls/process tree, writes outside declared paths, host namespace access, EDR/runtime alerts. | Quarantine node/workload, rotate reachable secrets, patch runtime/kernel, reduce privileges. |
| Secret in image/layer/log | Persist tới khi secret bị rotated; xóa tag không đảm bảo copies/cache biến mất. | Secret scanning alert, suspicious auth use, credential found in history/SBOM/log. | Rotate/revoke ngay, remove exposure, rebuild clean artifact, purge caches/registry per retention capability. |
6. Verification gate trước deploy
- Image reference resolve ra expected immutable digest; không deploy chỉ dựa vào mutable tag.
- Signature/attestation verification pass với đúng issuer/identity và repository policy.
- SBOM/provenance tồn tại nếu policy yêu cầu; builder/source/materials khớp expectation.
- Không có vulnerability vượt risk threshold trừ exception còn hạn, có owner và rationale.
- Runtime spec: non-root, no privileged/socket mount, capabilities tối thiểu, writable mounts rõ, resource/PID limits phù hợp.
- Secrets lấy từ runtime secret store; không xuất hiện trong Dockerfile, image history hoặc build logs.
7. Rollback, recovery và incident response
Giữ previous known-good digest và deployment metadata để rollback nhanh. Khi phát hiện artifact đáng ngờ, ưu tiên quarantine digest + revoke credentials + stop promotion; đừng chỉ retag vì tag không thay đổi content đã tồn tại. Rebuild sạch từ trusted source/builder sau khi root cause được xử lý, rồi verify lại attestations và runtime policy trước rollout.
Sau containment, kiểm tra nơi digest đã được deploy, secrets nào workload có thể đọc, node/registry/cache nào giữ artifact và log nào cần preserve. Recovery hoàn tất khi known-good digest được phục hồi, credentials đã rotate, policy gate ngăn tái diễn và monitoring không còn signal bất thường.