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_runon "Deploy to VPS"- Runs
smoke-test.shfrom 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:
- File existence: 8 REQUIRED_FILES (added
post-deploy-e2e.yml) - Workflow invariants (NEW): 8 content checks across 3 workflow files
- 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/CODEOWNERStồ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→ setrequire_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.ymlvào REQUIRED_FILES - CI GREEN:
check-critical-filespass 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 |