Để phát hiện lỗ hổng bảo mật trong repository hoàn toàn miễn phí, hãy kết hợp 3 lớp bảo vệ: công cụ quét dependency (npm audit, pip-audit hoặc OSV-Scanner), công cụ quét secret (Gitleaks) và công cụ quét mã nguồn (Semgrep Community Edition). Hãy chạy chúng trên mỗi pull request. Tuy nhiên, không có công cụ nào phát hiện được lỗi thiếu kiểm tra phân quyền (authorization), vì vậy bạn cần bổ sung thêm một bài kiểm tra khi ứng dụng đang chạy (runtime test) cho trường hợp đó.
npm audit --audit-level=high
pip-audit -r requirements.txt
gitleaks git . --no-banner
semgrep scan --config p/default --metrics=off --error
Vercel Security Review mang lại những thay đổi gì
Vercel Security Review là một tính năng của Vercel Agent, mở bản public beta từ ngày 2 tháng 11 năm 2026. Tính năng này quét từng lượt push lên repository GitHub đã kết nối, đọc phần diff và các đoạn code liên quan xung quanh, lần theo luồng thực thi để xem thay đổi đó có thể bị tác động từ đâu, đồng thời kiểm tra lại từng phát hiện trước khi báo cáo.
Ví dụ do chính Vercel đưa ra cũng chính là lý do bài viết này ra đời. Một thay đổi ở endpoint xử lý hóa đơn đã tra cứu hóa đơn theo ID mà không kiểm tra thông tin tổ chức (organization), khiến bất kỳ người dùng nào đã đăng nhập cũng có thể tải về hóa đơn của tổ chức khác. Đây là một lỗ hổng logic (logic flaw), và các công cụ quét mẫu code (pattern scanner) thường bất lực trước dạng lỗi này.
Dưới đây là đối tượng có thể sử dụng:
| Câu hỏi | Câu trả lời |
|---|---|
| Gói dịch vụ | Chỉ dành cho các nhóm Pro và Enterprise |
| Chi phí | Miễn phí đến ngày 10 tháng 11 năm 2026, sau đó tính theo giá token của nhà cung cấp cộng thêm 0,25 USD cho mỗi triệu token |
| Repository | Các GitHub repository đã kết nối; hiện chưa hỗ trợ những repository không deploy trên Vercel |
| Phạm vi quét | Bản diff so với nhánh gốc (base), hoặc toàn bộ mã nguồn trong lần review đầu tiên |
| Kết quả phát hiện | Dashboard theo dõi lỗ hổng, GitHub check và nhận xét (PR comments) trên các private và internal repository |
Tài liệu của Vercel cũng nêu rõ giới hạn: tính năng này chỉ phân tích mã nguồn chứ không phân tích ứng dụng đang chạy, đồng thời không phải là một bài kiểm thử xâm nhập (penetration test). Nếu bạn không đủ điều kiện sử dụng hoặc đang đọc bài viết này khi thời gian miễn phí đã kết thúc, phần còn lại của hướng dẫn này hoàn toàn không tốn một đồng chi phí nào.
Quá trình quét lỗ hổng repository cần bao gồm những gì
Một quy trình quét lỗ hổng bảo mật toàn diện cho repository cần kiểm tra 4 yếu tố: các lỗ hổng đã biết trong dependency, thông tin đăng nhập/khóa bí mật bị commit lên Git, các mẫu code không an toàn (chẳng hạn như lỗi injection), và logic phân quyền (authorization). Ba yếu tố đầu tiên đều đã có các công cụ quét miễn phí và hoàn thiện. Yếu tố thứ tư phụ thuộc vào ngữ cảnh nghiệp vụ của mã nguồn, do đó cần phải kiểm thử trực tiếp trên API đang chạy.

Một khóa bí mật dù đã bị xóa vẫn còn lưu lại trong lịch sử Git, vì vậy hãy quét toàn bộ lịch sử commit và thu hồi (rotate) ngay bất kỳ khóa thực tế nào. Đối với các khóa xuất hiện trong lưu lượng API và các test collection, hãy tham khảo hướng dẫn kiểm tra rò rỉ API key của chúng tôi.
So sánh các công cụ quét lỗ hổng miễn phí
Mức giá và giấy phép đã được kiểm tra vào ngày 5 tháng 11 năm 2026. Không có công cụ dòng lệnh (CLI) nào trong hướng dẫn này yêu cầu tài khoản hay thẻ thanh toán để thực thi các lệnh được nêu.
| Công cụ | Phát hiện | Chi phí và giấy phép | Điểm cần lưu ý |
|---|---|---|---|
npm audit |
Lỗ hổng dependency của npm | Miễn phí, đi kèm sẵn với npm | Cần có file lockfile |
| pip-audit | Lỗ hổng dependency của Python | Miễn phí, giấy phép Apache-2.0 | Chỉ hỗ trợ Python |
| OSV-Scanner | Lỗ hổng dependency trên nhiều hệ sinh thái | Miễn phí, giấy phép Apache-2.0 | Báo cáo nhiều hơn nên sẽ mất thời gian sàng lọc (triage) |
| Trivy | Dependency, secret, cấu hình sai | Miễn phí, giấy phép Apache-2.0 | Cần ghim phiên bản cố định (xem bên dưới) |
| Gitleaks | Secret trong lịch sử Git | Miễn phí, giấy phép MIT | GitHub Action của công cụ này yêu cầu license key miễn phí đối với các organization |
| Semgrep Community Edition | Mẫu code không an toàn, một số loại secret | Miễn phí, engine giấy phép LGPL-2.1 | Không thể theo dõi luồng dữ liệu vượt ra ngoài một hàm hoặc một file đơn lẻ |
| Dependabot alerts | Lỗ hổng dependency | Miễn phí cho cả public và private repository | Chỉ dành cho GitHub |
| GitHub secret scanning | Secret | Miễn phí cho public repository; 19 USD/active committer/tháng cho private repository | Private repository cần bật Secret Protection |
| CodeQL | Mẫu code không an toàn | Miễn phí cho public repository; 30 USD/active committer/tháng cho private repository | Private repository cần bật Code Security |
Hai lưu ý về vấn đề giấy phép: Bộ quy tắc cộng đồng của Semgrep sử dụng Semgrep Rules License, cho phép sử dụng nội bộ trong doanh nghiệp nhưng không cho phép phân phối lại hoặc cung cấp dưới dạng dịch vụ. Còn nếu bạn sử dụng Trivy, hãy xem kỹ CVE-2026-33634: kẻ tấn công đã từng xâm nhập vào một số thành phần trong hệ sinh thái Trivy vào tháng 3 năm 2026. Hãy chạy bản phát hành mới nhất và ghim bất kỳ GitHub Action nào vào mã commit SHA cụ thể.
Quét repository chỉ với vài dòng lệnh: kết quả thử nghiệm thực tế
Chúng tôi đã xây dựng một API hóa đơn nhỏ bằng Express và commit vào một repository cục bộ. Ứng dụng này sử dụng 4 npm dependency và 3 Python dependency ở phiên bản cũ, chứa 2 khóa giả lập (một khóa định dạng Stripe, một khóa định dạng AWS), một lỗi SQL injection, một lỗi command injection và một route trả về hóa đơn của bất kỳ tổ chức nào cho mọi người dùng đã đăng nhập.
Sau đó, chúng tôi chạy từng công cụ trên macOS vào ngày 5 tháng 11 năm 2026:
npm audit
pip-audit -r requirements.txt --no-deps --disable-pip
osv-scanner scan source -r .
trivy fs --scanners vuln,secret .
gitleaks git . --no-banner
semgrep scan --config p/default --metrics=off
semgrep scan --config p/nodejsscan --metrics=off
| Công cụ (phiên bản) | Phát hiện được | Bỏ sót |
|---|---|---|
npm audit (npm 11.12.1) |
9 package có lỗ hổng: 6 mức high, 3 mức low | Mọi thứ không phải là package npm |
| pip-audit 2.10.1 | 16 cảnh báo bảo mật trên 3 package đã ghim | Các package phụ thuộc gián tiếp (transitive package), do chúng tôi đã truyền cờ --no-deps |
| OSV-Scanner 2.7.0 | 66 cảnh báo bảo mật riêng biệt trên 15 package, bao gồm cả các package Python phụ thuộc gián tiếp | Secret và lỗi trong mã nguồn |
| Trivy 0.76.1 | 33 phát hiện về dependency và khóa định dạng Stripe | Khóa định dạng AWS |
| Gitleaks 8.30.1 | Khóa định dạng Stripe | Khóa định dạng AWS |
Semgrep 1.183.0, p/default |
Khóa định dạng Stripe, command injection, ghi chú thiếu middleware CSRF | SQL injection, khóa định dạng AWS |
Semgrep 1.183.0, p/nodejsscan |
SQL injection, command injection, khóa định dạng AWS | Khóa định dạng Stripe |
Có 3 điểm đáng chú ý rút ra từ kết quả này:
- Không thể so sánh đơn thuần bằng số lượng. Package, cảnh báo bảo mật (advisory) và phát hiện (finding) là các đơn vị hoàn toàn khác nhau, và mỗi công cụ lại phân tích dữ liệu theo cách riêng. Hãy so sánh xem công cụ đã phát hiện được những gì, thay vì chỉ nhìn vào tổng số lượng.
- Một công cụ quét secret đơn lẻ là chưa đủ. Cả Gitleaks và Trivy đều bỏ sót khóa định dạng AWS.
- Bộ quy tắc (ruleset) đóng vai trò quyết định. Bộ quy tắc mặc định của Semgrep đã bỏ qua một câu truy vấn SQL ghép chuỗi thông thường. Các bộ
p/javascript,p/nodejs,p/owasp-top-tenvàp/sql-injectionđều không đưa ra cảnh báo nào trên repo này, trong khip/nodejsscanlại phát hiện ra.
Không có công cụ nào cảnh báo route hóa đơn nói trên. Đây chỉ là một repo thử nghiệm nhỏ, vì vậy hãy coi đây là ví dụ minh họa chứ không phải bài đánh giá hiệu năng (benchmark) toàn diện. Chúng tôi không thử nghiệm với CodeQL.
Quét GitHub repository tự động trên mỗi pull request
Các runner tiêu chuẩn do GitHub host hoàn toàn miễn phí trên public repo. Với private repo, gói GitHub Free cung cấp hạn mức 12 USD mỗi tháng, tương đương khoảng 2.000 phút chạy trên runner Linux 2 core theo biểu giá công bố. Workflow dưới đây sử dụng trực tiếp các câu lệnh thông thường, giúp các organization không cần đến license key của Gitleaks Action:
name: repo-scan
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7 # pin to a commit SHA
with:
fetch-depth: 0
- name: Dependencies (npm)
run: npm audit --audit-level=high
- name: Dependencies (Python)
run: pipx run pip-audit -r requirements.txt
- name: Secrets
run: |
curl -sSL https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_linux_x64.tar.gz | tar xz gitleaks
./gitleaks git . --no-banner
- name: Code patterns
run: pipx run semgrep scan --config p/default --config p/nodejsscan --metrics=off --error
Cả 4 công cụ quét đều trả về mã thoát (exit code) 1 trên repo thử nghiệm của chúng tôi, và mã thoát khác 0 chính là dấu hiệu làm fail job. Bạn có thể bỏ bớt các bước mà tech stack của mình không cần tới. Để tích hợp kiểm thử API vào cùng pipeline này, hãy xem bài viết sử dụng Apidog CLI với GitHub Actions.
Bạn cũng nên bật Dependabot alerts. Tính năng này miễn phí trên mọi gói dịch vụ và tự động cảnh báo mà không cần đợi đến khi có pull request.
Lỗ hổng bảo mật: những lỗi phân quyền mà các công cụ quét thường bỏ sót
Các lỗi phân quyền (authorization) rất khó phát hiện đối với những công cụ quét theo mẫu, bởi mã nguồn nhìn bề ngoài trông hoàn toàn chuẩn xác: câu truy vấn hợp lệ, tham số hợp lệ, có middleware auth bảo vệ phía trước. Điểm yếu ở đây nằm ở một điều kiện bị thiếu sót, và chỉ có mô hình dữ liệu (data model) của bạn mới xác định được điều kiện đó bắt buộc phải tồn tại.
// Every scanner passed this
db.query("SELECT * FROM invoices WHERE id = $1", [req.params.id]);
// The fix: scope the lookup to the caller's organization
db.query("SELECT * FROM invoices WHERE id = $1 AND org_id = $2",
[req.params.id, req.user.orgId]);
Đây chính là lỗ hổng Broken Object Level Authorization (BOLA), đứng vị trí số 1 trong danh sách OWASP API Security Top 10 2023. OWASP khuyến nghị nên kiểm tra quyền truy cập trên mọi request có sử dụng ID do client cung cấp, đồng thời viết các bài kiểm thử để sớm phát hiện lỗi phân quyền trước khi triển khai sản phẩm.
Sử dụng một coding agent (AI hỗ trợ lập trình) có thể đem lại hiệu quả. Chúng tôi đã xóa các ghi chú trong repo thử nghiệm và yêu cầu Claude Code review, cả trường hợp có và không có gợi ý về tổ chức (organization). Trong cả hai lần, Claude Code đều chỉ ra vấn đề ở route hóa đơn. Tuy nhiên, giải pháp này không hoàn toàn miễn phí vì tiêu tốn chi phí trong gói dịch vụ agent của bạn, đồng thời kết quả giữa các lần chạy có thể không đồng nhất.
Một bài test tự động sẽ cho bạn câu trả lời dứt khoát đạt hay không đạt trên từng pull request. Để bao phủ kiểm thử phía API, hãy tham khảo bài viết tự động phát hiện lỗ hổng API, tổng hợp các công cụ quét bảo mật API và checklist kiểm thử bảo mật API của chúng tôi.
Để coding agent kiểm thử phân quyền với Apidog CLI
Bạn không cần phải viết tay các bài test này cho từng route. Hãy để coding agent thực hiện điều đó với Apidog CLI: công cụ sẽ đọc các route, tạo kịch bản test cho từng tài nguyên được bảo vệ và xây dựng một bộ test suite hoàn chỉnh để chạy trong CI. Gói Apidog Free hỗ trợ tối đa 4 người dùng.
npm install -g apidog-cli@latest
apidog auth login --with-token <YOUR_TOKEN>
apidog skill install
Bạn sẽ cần một môi trường kiểm thử với dữ liệu khởi tạo (seed) gồm 2 tổ chức và mỗi tổ chức có 1 người dùng. Sau đó, chỉ cần cung cấp cho agent một câu prompt:
Read the routes in src/. For each route that returns data owned by an
organization, create an Apidog test scenario in project <id>: log in as
the Org A test user, request an Org B resource by ID, and assert the
status is 403 or 404. Add an Org A request for its own resource and
assert 200, so a broken login can't pass. Group the scenarios in a test
suite, run it against the staging environment, and summarize failures.
Agent sẽ kiểm tra cấu trúc payload, tạo các scenario và thực thi test suite:
apidog cli-schema get test-scenario-create
apidog cli-schema validate test-scenario-create --file scenario.json
apidog test-scenario create --project <id> --file scenario.json
apidog test-scenario import-steps <scenarioId> --project <id> --source endpoint --ids <endpointIds>
apidog test-suite create --project <id> --file suite.json
apidog run --test-suite <suiteId> --project <id> -e <envId> -r cli,junit

Bước kiểm tra trường hợp hợp lệ (positive check) rất quan trọng. Nếu không có bước này, một base URL sai cũng có thể trả về 404 và bài test sẽ pass vì lý do sai lệch.
Hãy thêm câu lệnh apidog run tương tự vào workflow ở trên, chạy đối chiếu với môi trường preview hoặc staging chứa dữ liệu tổ chức thử nghiệm đã seed, tuyệt đối không dùng dữ liệu production. Tài liệu tham chiếu lệnh apidog run sẽ giải thích chi tiết các flag khác, và bài viết hướng dẫn sử dụng Apidog CLI trong Claude Code sẽ hướng dẫn từng bước thiết lập agent.
Câu hỏi thường gặp
Cách tốt nhất để phát hiện lỗ hổng trong repository hoàn toàn miễn phí là gì? Hãy kết hợp một công cụ quét dependency, Gitleaks và Semgrep Community Edition, sau đó bổ sung thêm một bài runtime test để kiểm tra phân quyền. Không có một công cụ đơn lẻ nào có thể bao quát toàn bộ các vấn đề trong repo thử nghiệm của chúng tôi.
Vercel Security Review có miễn phí không? Tính năng này chỉ miễn phí đến ngày 10 tháng 11 năm 2026 và chỉ áp dụng cho các nhóm Pro và Enterprise. Sau thời gian đó, bạn sẽ phải trả phí theo giá token của nhà cung cấp cộng thêm 0,25 USD cho mỗi triệu token. Hiện tại, các repository không deploy trên Vercel vẫn chưa được hỗ trợ.
Tính năng quét secret của GitHub có miễn phí trên private repo không? Không. Tính năng quét secret và CodeQL chỉ miễn phí trên public repo, còn private repo cần đăng ký GitHub Secret Protection (19 USD) hoặc GitHub Code Security (30 USD) cho mỗi active committer mỗi tháng. Riêng Dependabot alerts thì miễn phí trên cả hai loại repo.
Semgrep có thể tìm ra lỗi phân quyền không? Với các bộ quy tắc mà chúng tôi đã chạy, Semgrep không hề cảnh báo route hóa đơn trong thử nghiệm. Phiên bản Community Edition không thể theo dõi luồng dữ liệu vượt ra ngoài một hàm hoặc một file, dù bạn vẫn có thể tự viết các rule tùy chỉnh cho những mẫu code đặc thù trong codebase của mình.
Các công cụ quét có thể thay thế kiểm thử xâm nhập (penetration test) không? Không. Các công cụ quét và bài test chỉ bao quát được những mẫu đã biết và các trường hợp bạn đã lường trước trong kịch bản. Kiểm thử xâm nhập nhằm mục đích tìm kiếm những kẽ hở mà bạn chưa từng nghĩ tới, và tài liệu của chính Vercel cũng nêu rõ tính năng review của họ không phải là một bài penetration test.
