Skill: orca-sec-scans
WHAT
Purpose và context
- Purpose: Một luồng quét bảo mật static, chỉ-đọc (Trivy không sửa mã khi quét), dùng được local lẫn CI/Jenkins. Bao trùm: dependency CVE (Go/Node/Python lockfile), misconfig (Dockerfile/compose/nginx), và secret lộ trong file.
Ngoài lớp static đó còn hai lớp: quét ĐỘNG kiểm chứng giả định mặc định của dev bằng request thật, và quét RA NGOÀI (chuỗi cung ứng/thương hiệu, keyless).
- Trigger (when to use):
- User nói "quét bảo mật", "scan", "trivy", "check CVE", "security scan", "có lỗ hổng không"
- Trước khi release / merge nhánh deploy
- Định kỳ trong CI (
trivy fs . --config trivy.yaml --exit-code 1
)
- Diff rơi vào bảng Trigger-conditions (auth, input người dùng, secret, endpoint mới, thanh toán/dữ liệu nhạy cảm, đưa app ra public domain) → BẮT BUỘC scan; user nói "có lỗ hổng không", "an toàn chưa" → luôn là trigger.
- Non-goals: không auto-bump hàng loạt khi submodule có thay đổi chưa commit; không xoá finding khỏi report (chấp nhận thì ghi ); không commit report lên server deploy; không điều tra mối đe doạ ngoài diện rộng kiểu cti-expert (chỉ mẩu supply-watch keyless).
Mental model
Trivy có chưa? → scope (lockfile) → quét static HIGH/CRITICAL → report JSON+HTML → tóm tắt + đề xuất fix → re-scan NONE
, song song
giả định dev → request thật (curl/dig/git diff) → xác nhận hoặc lỗ hổng
, cộng tuỳ chọn
tên thương hiệu → biến thể tất định → DNS sống + CT log
. Static sạch KHÔNG có nghĩa là an toàn.
Input và output contract
| Field | Required? | Ý nghĩa |
|---|
| In | thư mục mã nguồn (be, fe hoặc ) | có | target quét; nếu repo có |
| In | HOST / domain đang chạy | cho quét động | để curl/dig kiểm chứng thật |
| In | tên thương hiệu | không | cho |
| Out | security/trivy-report.json
+ security/trivy-report.html
| có | report đầy đủ, chỉ là artifact review |
| Out | bảng HIGH/CRITICAL theo target + đề xuất fix | có | bump deps, USER non-root, xoay secret |
| Out | kết quả quét động | có | từng giả định: đúng/sai kèm lệnh + mã HTTP/DNS thật |
| Out | kết quả re-scan | khi có fix | |
| Out | báo cáo supply-watch | tuỳ chọn | rc 0 sạch, 2 có phát hiện; crt.sh lỗi → BỎ QUA |
Rules và capabilities
- RULE-01 (MUST): Static (Trivy) + Động (checklist trên) là HAI lớp khác nhau — chạy CẢ HAI. Trivy bắt CVE/misconfig/secret-in-file; nó KHÔNG bắt auth bypass, public exposure, CORS/CSRF logic, lệch branch. Đừng coi report Trivy sạch = an toàn.
- RULE-02 (MUST): Không tin giả định mặc định của dev — mọi "đã có login", "nội bộ nên an toàn", "chạy được rồi" phải kiểm chứng bằng request thật trước khi kết luận.
- RULE-03 (MUST): Trivy không sửa mã khi quét — an toàn chạy bất kỳ lúc nào.
- RULE-04 (MUST): Finding đã review & chấp nhận → ghi vào (1 ID/dòng + comment lý do + ngày), KHÔNG xoá khỏi report.
- RULE-05 (MUST): Không commit lên server deploy — chỉ là artifact review.
- RULE-06 (MUST): Khi deploy bonbon-ai: chỉ push và (2 submodule) lên server; tooling (trivy.yaml, security/, skill) không lên server.
- RULE-07 (MUST): Mọi thay đổi fix phải qua build/verify trước khi commit (, , …).
- Capabilities: cài công cụ quét cục bộ nếu thiếu; quét static chỉ-đọc mã nguồn; gửi request HTTP/DNS thật tới host của chính dự án; sửa manifest/Dockerfile khi được áp fix; đọc CT log/DNS công khai (keyless).
Failure boundaries
- Không cài được Trivy → blocked, báo user.
- Submodule có thay đổi chưa commit → chỉ đề xuất fix, không auto-bump.
- Fix không build được (, ) → failed, không commit.
- Không có HOST để quét động → partial: chỉ static, nói rõ lớp động CHƯA chạy, không kết luận "an toàn".
- Secret bị flag → xoay key ngay (không chỉ xoá khỏi file).
- supply-watch không gọi được crt.sh → BỎ QUA, không phán sạch.
HOW
Main workflow
| Step | Type | Inputs | Action | Outputs/exit | Failure/next |
|---|
| W01 | effect | máy | Bước 0 — Check + Install Trivy (BẮT BUỘC chạy trước) | in ra | cài lỗi → blocked |
| W02 | deterministic | repo | Bước 1 — Detect ngôn ngữ qua lockfile, bỏ thư mục build/vendor | scope | — |
| W03 | deterministic | scope | Bước 2 — Quét vuln + misconfig + secret, HIGH/CRITICAL trước | findings | — |
| W04 | deterministic | findings | Bước 3 — Xuất report JSON + HTML vào | 2 file report | — |
| W05 | judgment | findings | Bước 4 — Tóm tắt HIGH/CRITICAL theo target + đề xuất fix | bảng + đề xuất | submodule bẩn → chỉ đề xuất |
| W06 | deterministic | target đã fix | Bước 5 — Re-scan xác nhận | | còn → quay W05 |
| W07 | effect | HOST, diff | Quét ĐỘNG: chạy checklist 8 giả định dev bằng request thật | từng giả định có bằng chứng | không HOST → partial |
| W08 | deterministic | tên thương hiệu | Quét RA NGOÀI bằng (B03) | rc 0 hoặc 2 | crt.sh lỗi → BỎ QUA |
Chi tiết từng bước (nguồn chân lý cho W01–W08):
Workflow
Bước 0 — Check + Install Trivy (BẮT BUỘC chạy trước)
bash
if ! command -v trivy >/dev/null 2>&1; then
echo "Trivy chưa có → cài…"
if [[ "$(uname)" == "Darwin" ]]; then
brew install trivy
else
# Linux: dùng script chính thức Aqua (không cần root nếu set BINDIR)
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
| sh -s -- -b /usr/local/bin
fi
fi
trivy --version # xác nhận; DB vuln tự cập nhật lần chạy đầu
Bước 1 — Detect ngôn ngữ (scope quét)
Tìm lockfile để biết hệ sinh thái:
/
(Go),
/
(Node),
/
(Python). Bỏ qua
,
,
,
,
.
Bước 2 — Quét (HIGH+CRITICAL trước cho nhanh)
bash
trivy fs <dir> \
--scanners vuln,misconfig,secret \
--severity HIGH,CRITICAL \
--skip-dirs '**/node_modules' --skip-dirs '**/.next' \
--skip-dirs '**/.contentlayer' --skip-dirs '_archives' \
--no-progress
Repo bonbon-ai: quét riêng
và
(mỗi cái là submodule). Ưu tiên
nếu repo đã có.
Bước 3 — Xuất report đầy đủ
bash
mkdir -p security
TPL=$(find $(brew --prefix trivy 2>/dev/null || echo /opt/homebrew) -name html.tpl 2>/dev/null | head -1)
trivy fs . <cờ skip-dirs như trên> --no-progress -f json -o security/trivy-report.json
trivy fs . <cờ skip-dirs như trên> --no-progress -f template --template "@$TPL" -o security/trivy-report.html
Bước 4 — Tóm tắt & đề xuất fix
Đếm HIGH/CRITICAL theo từng target, in bảng. Sau đó đề xuất (KHÔNG auto-bump hàng loạt nếu submodule đang có thay đổi chưa commit):
- Dep bump dễ (direct dep, sửa thẳng manifest): vd trong .
- Dep indirect: rồi verify. Lưu ý có thể nâng directive ; nếu vượt base image trong Dockerfile thì bump luôn cho khớp.
- Misconfig DS-0002 (root user): thêm non-root vào Dockerfile ( alpine, debian, hoặc cho image node-alpine; nhớ thư mục ghi như volume/data).
- Secret: nếu Trivy flag → xoay key ngay, không chỉ xoá khỏi file.
Bước 5 — Re-scan xác nhận
Chạy lại Bước 2 trên target đã fix, xác nhận
.
Quét RA NGOÀI — chuỗi cung ứng & thương hiệu (chân thứ ba, keyless)
Hai phần trên đều nhìn VÀO TRONG dự án. Không gì nhìn RA NGOÀI: ai đang dựng domain hoặc package na ná tên bạn để lừa người dùng, hoặc để chèn một dependency giả vào lệnh cài của chính bạn.
bash
python3 fdk/tools/supply-watch.py <tên-thương-hiệu> # sweep mặc định 7 TLD
python3 fdk/tools/supply-watch.py <tên> --tld com,dev --json # cho CI
python3 fdk/tools/supply-watch.py --self-test
Sinh biến thể
tất định, offline theo sáu kiểu — bỏ chữ, lặp chữ, đảo chữ, gõ nhầm phím kề (bàn phím QWERTY), chữ nhìn giống (
→
,
→
), thêm gạch nối — rồi hỏi DNS xem cái nào
đang sống. Kèm CT monitor đọc Certificate Transparency (crt.sh) xem có chứng chỉ nào vừa được cấp cho domain na ná.
Không cần API key, không cần
. Mã thoát:
sạch ·
có phát hiện. Không gọi được crt.sh thì nó nói
BỎ QUA, không phán là sạch.
Hấp thụ hẹp từ
(workflow 08). Cố ý
chỉ lấy mẩu này: cti-expert là 121 op + 78 MCP tool để điều tra mối đe doạ bên ngoài, cần
+ API key + mạng outbound. Gộp nguyên khối là kéo phụ thuộc key/mạng vào một cổng đang keyless và chạy được offline.
Quét ĐỘNG — kiểm chứng giả định của dev (bổ sung cho Trivy)
Nguyên tắc: Trivy (static) KHÔNG bắt được lỗi kiến trúc/logic/cấu hình runtime. Lỗ hổng nặng nhất thường nằm ở giả định mặc định của developer — phải kiểm chứng bằng request thật, không tin lời. "Chạy được" ≠ "an toàn".
Đúc kết từ sự cố 22/06/2026: API ETL payroll không có auth (auth chỉ ở tầng web, path qua nginx đi vòng qua) → ai cũng lấy được lương + PII 3.637 NV; tưởng "nội bộ" nhưng có domain public (IP public) bắc cầu ra cả internet. Trivy không phát hiện — chỉ / thật mới ra.
Checklist "ĐỪNG TIN — phải kiểm chứng" (dev assumption → thực tế → cách verify)
-
"API sau reverse proxy được bảo vệ vì web/UI có login."
→ SAI: auth thường chỉ ở tầng web; path proxy (
,
...) browser gọi thẳng nên đi VÒNG qua login.
→ Verify:
THẲNG từng route API
không kèm cookie/token → phải
. Nếu
+data = lỗ hổng. Auth phải ở tầng API/proxy (vd nginx
), KHÔNG chỉ ở UI.
bash
for p in data/stats/all report/export sync/status; do
curl -k -o /dev/null -w "$p -> %{http_code}\n" https://HOST/etl/$p; done # mong đợi 401
-
"Server nội bộ / IP private (192.168.x) nên ngoài không vào được."
→ SAI: một public domain /
/ port-forward có thể bắc cầu vào.
→ Verify:
dig +short <mọi subdomain khả dĩ>
→ có IP public không? Thử curl từ mạng ngoài. KHÔNG tin "nội bộ" — kiểm DNS thật.
-
"Mở CORS là lỗ hổng / đóng CORS là đủ an toàn."
→ SAI HƯỚNG: CORS chỉ chặn
browser ĐỌC cross-origin. KHÔNG chặn
/script; KHÔNG chặn
CSRF GHI (POST query-param / không-body =
simple request → không preflight → server chạy bất kể CORS). Lỗ thật thường là
no-auth + port mở. Đừng tốn công CORS khi cửa chính (auth) chưa khóa.
-
"Config mặc định để nguyên là ổn."
→ Check biến default lọt prod:
còn
? secret/flag còn giá trị mẫu?
vô tình
?
bash
curl -k -D- -o /dev/null -H "Origin: http://localhost:3000" https://HOST/etl/health | grep -i access-control
-
"Branch nào deploy cũng như nhau."
→ SAI: CI (Jenkins) clone branch X nhưng server chạy branch Y → lệch. Merge conflict có thể
rớt nguyên block (vd
trong compose →
, deploy fail).
→ Verify: branch CI clone == branch đang chạy?
git diff <ci-branch> <running-branch> -- docker-compose.yml .env* deploy/
.
-
"paramiko/SSH kết nối được là xong."
→
/
KHÔNG verify host key → MITM đánh cắp pass + file. Verify: phải pin known_hosts +
.
-
"Token/secret truyền sao cũng được."
→ Token trong URL
→ vào nginx/uvicorn access-log, Referer, history. Verify: secret đi qua
header/cookie, KHÔNG qua query string.
-
" cho tiện."
→ Trả mọi cột gồm PII (CCCD/MST/BHXH/lương) +
toàn-cột làm oracle dò giá trị. Verify: whitelist cột trả về; search không quét cột nhạy cảm.
Trigger-conditions — hành vi code nào BẮT BUỘC scan
Không chờ ai nhớ gọi skill — diff rơi vào bảng là nghĩa vụ scan kích hoạt (distill từ
WorldFlowAI/everything-claude-code
security-review):
| Thay đổi vừa làm | Bắt buộc | Vì sao |
|---|
| Thêm/sửa auth, session, phân quyền | Trivy + quét động | Token để localStorage dính XSS, thiếu check role trước thao tác nhạy cảm — lớp lỗi authorization là thứ Trivy không thấy. |
| Nhận input người dùng (form, param, upload) | Trivy + quét động | Input không validate bằng schema + file upload không giới hạn size/type/extension là cửa vào SQLi/XSS/RCE. |
| Đụng secret / credential / API key | Trivy (secret scan) | Key hardcode trong source hoặc lọt git history — phải ở env var và platform secret, phải gitignore. |
| Mở API endpoint mới | Trivy + quét động | Endpoint mới mặc định THIẾU rate-limit + CSRF + check quyền; error message dễ lộ chi tiết nội bộ/stack trace. |
| Thanh toán / dữ liệu nhạy cảm | Trivy + quét động + review tay | PII/tiền không được vào log, error phải generic; một lỗ là compromise cả nền tảng — err on the side of caution. |
| Đưa app ra public domain / đổi reverse proxy | Quét động | Lỗ no-auth "nội bộ" biến thành internet-exposed đúng lúc đó (checklist giả định dev ở trên). |
Không rơi vào bảng → scan theo nhịp release là đủ. Câu tự kiểm: "diff này có làm một trong 6 việc trên không?" — trả lời được dưới một phút. User nói "có lỗ hổng không", "an toàn chưa" → luôn là trigger.
Branches
| ID | Kind | Guard | Hành vi | Skip / failure | Rejoin |
|---|
| B01 | conditional_required | repo bonbon-ai | quét riêng và (mỗi cái là submodule); deploy chỉ push 2 submodule đó | repo khác → quét | W04 |
| B02 | conditional_required | repo đã có | ưu tiên | không có → cờ skip-dirs mặc định | W04 |
| B03 | user_optional | user muốn soi chuỗi cung ứng / thương hiệu | sweep 7 TLD + CT monitor | không yêu cầu → skip | kết thúc |
| B04 | conditional_required | finding đã review và chấp nhận | ghi (1 ID/dòng + lý do + ngày), không xoá khỏi report | — | W06 |
| B05 | conditional_required | Trivy flag secret | xoay key ngay, không chỉ xoá khỏi file | — | W06 |
Validation và stopping
Tất định: rc/output của Trivy (re-scan
), mã HTTP thật của curl (route API không token phải
),
thật,
branch, rc
. Fix chỉ commit sau build/verify xanh. Cần người: quyết chấp nhận finding vào
, review tay luồng thanh toán/dữ liệu nhạy cảm. Dừng khi re-scan sạch và mọi giả định trong checklist đã có bằng chứng; không kết luận "an toàn" chỉ từ Trivy.
Examples
- Positive: "quét bảo mật repo bonbon-ai" → Trivy đã có → quét riêng , → 2 HIGH: trong + DS-0002 root user → bump dep + thêm → build xanh → re-scan ; quét động curl không token ra .
- Boundary/failure: Trivy sạch nhưng curl thẳng không cookie trả + dữ liệu lương → lỗ hổng auth-bypass, báo nặng dù report static sạch (RULE-01); subdomain ra IP public → "nội bộ" là sai.
- Boundary: khi crt.sh không phản hồi → in BỎ QUA cho CT monitor, không báo sạch.
Origin
- Absorb 2026-07-17 (adapt_mode: dissolve, T-260717-02): bảng trigger-conditions distill từ
WorldFlowAI/everything-claude-code
(skills/security-review/SKILL.md
— When to Activate + 10 nhóm checklist). Clone depth-1 trong scratchpad/, không vendor bytes.