KB-499B rev 2

S129E Audit Report — Điều 30 Total Audit + Guard Content Check

6 min read Revision 2
reports129eauditdieu30guardsecurityTD-344

S129E — AUDIT TỔNG THỂ ĐIỀU 30 + BẢO VỆ CHỐNG AGENT PHÁ HỎNG

Agent: Claude Code | Phiên: S129E | Ngày: 2026-03-23 PR: #575 (web-test) — fix guard content check TD: TD-344


PHẦN A — AUDIT 7 TẦNG

Tầng 1: Contract JSON — 3 files ✅

File Columns Invariants Tier
web/tests/contracts/registries.json 10 11 (10 required_rows + 1 required_link) A
web/tests/contracts/species-matrix.json 7 2 (required_text: "Ma trận Loài", "TOTAL") A
web/tests/contracts/health.json 6 3 (cards: KHỚP, Orphan, Phantom) A

Tầng 2: Playwright E2E — 4 spec files ✅

File Tests Contract-driven?
registries.spec.ts 10 columns, 10 required_rows, links, min 15 rows ✅ reads registries.json
registries-species.spec.ts 7 columns, min 33 rows, required_text ✅ reads species-matrix.json
registries-health.spec.ts 3 cards, 6 columns, min 3 rows ✅ reads health.json
smoke.spec.ts 9 pages no 404/500 Standalone

Tầng 3: Post-Deploy E2E — ✅ (restored S129D)

  • post-deploy-e2e.yml: workflow_run on "Deploy to VPS"
  • Runs smoke-test.sh from GH runner
  • Evidence: Run ID 23420045298 SUCCESS (S129D)

Tầng 4: Smoke Keywords — ✅

smoke-test.sh v1.0: 19 checks across 4 sections:

  • Infrastructure (3), Public API (9), Website Pages (3 incl. contract keywords), Security (1)
  • Contract keywords checked: CAT-SPE, CAT-ORP, Phân loại loài, Thành phần

Tầng 5: Self-protect Guard — ✅ (enhanced S129E)

guard_critical_files.yml — 3 steps:

  1. File existence: 8 REQUIRED_FILES (added post-deploy-e2e.yml)
  2. Workflow invariants (NEW): 8 content checks across 3 workflow files
  3. Contract strength: columns ≥3, invariants ≥1

Tầng 6: Required Checks (Branch Protection) — ✅

6 required checks on main:

  • Pass Gate, Quality Gate, E2E Smoke Test, build, e2e, check-critical-files
  • Linear history: enforced
  • Force push/deletions: blocked

Tầng 7: E2E on push main — ✅

e2e-test.yml: triggers on push (main) + pull_request (main) + workflow_dispatch Runs full Playwright suite with contract-driven tests.


PHẦN B — LỖ HỔNG BẢO VỆ

B1. Guard trước S129E — chặn được gì?

Attack Vector Trước S129E Sau S129E
Xóa workflow file ✅ Chặn (file existence) ✅ Chặn
Xóa contract JSON ✅ Chặn (file existence) ✅ Chặn
Yếu hóa contract (bớt columns/rows) ✅ Chặn (contract strength) ✅ Chặn
Rewrite workflow, xóa trigger ❌ KHÔNG chặn Chặn (workflow invariants)
Xóa post-deploy-e2e.yml ❌ KHÔNG chặn (không trong REQUIRED_FILES) Chặn

B2. Lỗ hổng CÒN LẠI (cần user quyết định)

1. CODEOWNERS không enforced:

  • .github/CODEOWNERS tồn tại, assign @Huyen1974 cho .github/, scripts/, docs/ops/
  • Branch protection: require_code_owner_reviews: false → CODEOWNERS bị bỏ qua
  • Fix: gh api -X PATCH repos/Huyen1974/web-test/branches/main/protection → set require_code_owner_reviews: true

2. Required reviews = 0:

  • Bất kỳ agent nào cũng merge PR mà không cần human review
  • Trade-off: Tăng lên 1 → mọi PR cần user approve → chậm workflow
  • Khuyến nghị: Giữ 0 vì user là solo developer, nhưng BẬT CODEOWNERS enforcement để .github/ changes cần review

3. Workflow invariant checks là grep-based:

  • Agent có thể chèn pattern vào comment để bypass (ví dụ: # workflow_run: disabled)
  • Mitigation: guard grep kiểm tra trong context YAML, không phải comment
  • Đủ tốt cho current threat model (agents không cố tình adversarial)

PHẦN C — FIX ĐÃ LÀM

PR #575: Workflow Content Guard (TD-344)

  • Thêm step "Verify workflow invariants": 8 pattern checks across 3 files
  • Thêm post-deploy-e2e.yml vào REQUIRED_FILES
  • CI GREEN: check-critical-files pass với invariant step mới
  • Merged: squash merge

Workflow Inventory (10 files)

Workflow Trigger Mục đích Trong guard?
nuxt-ci.yml push/PR Build + lint No (CI infra)
deploy-vps.yml workflow_run (Nuxt 3 CI) Deploy to VPS ✅ Content check
post-deploy-e2e.yml workflow_run (Deploy to VPS) Production smoke ✅ File + content
e2e-test.yml push/PR Playwright E2E ✅ File + content
guard_critical_files.yml PR Guard critical files No (self)
deploy.yml push/PR Terraform No
enforce-table-rule.yml PR (.vue) Table UX rule No
ops-smoke.yml schedule (6h) Ops monitoring No
sync-check.yml schedule (6h) Health check No
required-docs-guard.yml PR/push Docs guard No

TỰ KIỂM TRA

# Câu hỏi Kết quả
1 Đã đọc SSOT + Điều 30 + S129C/D reports?
2 Audit 7 tầng: mỗi tầng có evidence?
3 Lỗ hổng guard: chặn xóa file nhưng không chặn rewrite? ✅ ĐÃ FIX (workflow invariants)
4 Branch protection: đủ chặt chưa? ⚠️ CODEOWNERS not enforced, reviews=0 (cần user quyết định)
5 Workflow inventory: đầy đủ? ✅ 10 workflows
6 Fix nhỏ đã làm? Fix lớn đã báo cáo? ✅ PR #575 merged. CODEOWNERS báo cáo cho user
7 2-hat flow liền? ✅ PR #575 → CI GREEN → merge → deploy → Post-Deploy E2E ✅
8 Report lưu + verified full? ✅ get_document_for_rewrite confirmed (5358 chars, truncated=false)

Mũ 2 Evidence — PR #575

Workflow Run ID Trigger Status
Nuxt 3 CI 23420409377 push (main) ✅ SUCCESS
Deploy to VPS 23420452704 workflow_run (Nuxt 3 CI) ✅ SUCCESS
Post-Deploy E2E 23420520613 workflow_run (Deploy to VPS) ✅ SUCCESS