vulngate
Agent-neutral security checks before you ship. Find, understand, and fix vulnerabilities in your code — whether it was written by Claude Code, Cursor, Codex, Windsurf, Gemini CLI, or a human.
We scan the code the agents produce — not the agents themselves. (Tools like skill/MCP supply-chain scanners secure the agent. vulngate secures the code that lands in your repo.)
Philosophy: $0 forever, bring-your-own-inference
- The core makes no LLM calls. vulngate orchestrates deterministic scanners (SAST, secrets, dependency audit) and normalizes their output. It costs nothing to run and sends your code to no one.
- Understanding and auto-fixing happen through your agent. A "vibe coder"
who can't read
CWE-78is already working inside an AI agent — so vulngate hands that agent structured findings (Phase 3, MCP) and it explains the risk in plain English and drafts the fix, on your subscription, not a maintainer's. - Even with no agent and no API key, you still get value: every finding
ships with a
plain_summary— one jargon-free sentence — from a built-in, offline knowledge pack. - CI is the enforcement point. An agent in an IDE can ignore instructions; a CI check blocks the merge. vulngate is CI-friendly from day one (stable exit codes, SARIF, JSON).
What it runs
| Scanner | Kind | Auto-runs when |
|---|---|---|
| Semgrep | SAST (code patterns) | source files are present |
| Gitleaks | Secrets | always (scans the tree) |
| pip-audit | Python deps | a requirements*.txt is present |
npm audit |
npm deps | a package-lock.json is present |
Missing a scanner? vulngate warns and skips it — it never crashes. Install scanners to widen coverage.
Install
# Core + the Python scanners (Semgrep, pip-audit) in one shot.
# PyPI publish is pending — until then, install from source:
# pip install "vulngate[scanners] @ git+https://github.com/cisoventures/vulngate.git"
pip install "vulngate[scanners]"
# Gitleaks is a Go binary (optional, for secret scanning):
brew install gitleaks # or see the gitleaks releases page
The core alone (pip install vulngate) has zero dependencies — it's pure
stdlib and will run, degrading gracefully to whatever scanners you have.
Usage
vulngate scan . # scan the current repo
vulngate scan ./src --fail-on medium # stricter threshold
vulngate scan . --sarif results.sarif
vulngate gate findings.json # re-check an existing report against the threshold (exit code only)
vulngate sarif findings.json --out results.sarif # project a findings.json to SARIF
Outputs, every run:
- a pretty terminal summary grouped by severity, each finding with a
plain-English line and a fix hint. Vulnerable dependencies are labelled
in your live appvsbuild-only tool(a flaw in your build toolchain is not the same risk as one in shipped code), code-pattern findings carry a "this can be a false alarm — confirm it applies" caveat, and a short glossary defines any jargon that appears; findings.json— the normalized schema (seeschemas/findings.schema.json), including a scan receipt (scan.receipt: commit, config hash, scanner versions, timestamps) so a report is self-describing and auditable;- optional SARIF for GitHub code scanning.
Every scanner's outcome is recorded with an honest status —
completed · not_applicable (nothing to scan) · unavailable (not installed)
· disabled (config) · error — and the overall scan.status
(complete / partial / no_coverage / error) is derived from them, so a
0 findings result is never confused with a scanner that didn't run.
Exit codes (CI-friendly)
| Code | Meaning |
|---|---|
0 |
clean, or nothing at/above the --fail-on threshold |
1 |
at least one finding at/above the threshold (default: high) |
2 |
tool error (bad target/config, or every applicable scanner failed) |
A missing scanner is a skip with a warning — not exit 2.
Zero-config, with optional config
Drop a vulngate.toml at your repo root (all keys optional; reused identically
by every later phase):
fail_on = "high" # critical | high | medium | low
exclude = ["tests/*", "*.min.js"]
disable = ["gitleaks"] # scanner names to skip
ignore = ["python.lang.security.audit.some-rule", "vg_ab12cd..."] # rule or finding id
fail_on_dev_deps = true # do build-only (dev) dependency flaws block the gate?
Build-only vs live-app dependencies. A vulnerable build-only dependency
(your dev toolchain — bundlers, test runners, CLIs) never ships to the running
app, so it isn't the same risk as a flaw in a package your app actually runs.
By default vulngate is strict (build-only flaws still block). For an app-team or
vibecoder setup, set fail_on_dev_deps = false (or pass --ignore-dev-deps, or
the Action's ignore-dev-deps: true): build-only flaws are still reported,
just not treated as blocking. The local MCP server — the vibecoder agent loop —
uses this lenient behavior by default.
Use it in CI (the enforcement point)
Add the Action to block merges on findings at/above your threshold:
# .github/workflows/vulngate.yml
name: vulngate
on: pull_request
permissions:
contents: read
pull-requests: write # for the PR comment
security-events: write # for SARIF upload
actions: read # required by the SARIF upload action
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: cisoventures/vulngate@v1
with:
fail-on: high
# ignore-dev-deps: true # build-only dep flaws: report, don't block
# anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }} # optional: your key → LLM triage + fix suggestions
It upserts a single PR comment (never spams), uploads SARIF to the Security
tab, and fails the check above the threshold. See action/ for all
inputs. The optional LLM triage runs on your key — omit it and the free
deterministic gate is fully useful.
Private repos: uploading SARIF to the Security tab needs a public repo or
GitHub Advanced Security. vulngate detects when code scanning isn't available and
skips the upload rather than failing your build — a passing scan always stays
a passing build. (Set upload-sarif: false to skip the check entirely.)
Use it with your agent (the vibe-coder loop)
Install the local MCP server (no hosting, no key) and your agent — Claude Code, Cursor, Codex, Windsurf — can scan, explain in plain English, and draft fixes on your own subscription:
pip install "vulngate[mcp,scanners]"
claude mcp add vulngate -- vulngate-mcp # Claude Code; other agents in mcp-server/
Then: "scan my repo" → "what's the worst one?" (plain-English explanation) →
"fix it" (the agent drafts a patch, you approve). The server is read-only except
for writing findings.json; it never writes code and makes no LLM calls itself.
See mcp-server/ for per-agent config.
Roadmap
| Phase | What | Status |
|---|---|---|
| 1 | CLI core — orchestrate + normalize + SARIF/JSON + exit codes | ✅ shipped |
| 2 | GitHub Action — PR comment, SARIF upload, threshold gate, optional BYO-key LLM triage | ✅ shipped |
| 3 | MCP server — scan_repo / explain_finding / suggest_patch / verify_fix for your agent (the flagship vibe-coder loop) |
✅ shipped |
| 4 | Instruction adapters — SKILL.md, .cursor/rules, AGENTS.md + distribution |
✅ shipped |
Each phase is independently useful — stopping after any one leaves a complete tool.
Contributing
Community-maintained, no SLA — see CONTRIBUTING.md. The easiest first contribution is a new entry in the plain-English knowledge pack. Questions → GitHub Discussions.
License
MIT. vulngate is complementary to vendor-native security tooling, including Anthropic's Claude-native security suite — this is the universal on-ramp; theirs is the Claude-native deep end.
Metadata
Release files for vulngate 1.5.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vulngate-1.5.3.tar.gz | 61.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vulngate-1.5.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 102.7 kB
Release files / vulngate-1.5.3.tar.gz
| Download URL | vulngate-1.5.3.tar.gz |
|---|---|
| Size | 61.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
39d19a43399e0d0a08406d5f88d9df05ae42ed2c661f909ed1a2fa0487ee7907
|
|
BLAKE2b-256 checksum How to use checksums |
a52a7fbfcdb79acf36f82120c3a7826094e1f79d40157263f36a5320bfbe2763
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / vulngate-1.5.3-py3-none-any.whl
| Download URL | vulngate-1.5.3-py3-none-any.whl |
|---|---|
| Size | 41.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9c202fcdbb7af700d1537ed5c7021251228b2963b34fd8ad7ce67b3e637934b1
|
|
BLAKE2b-256 checksum How to use checksums |
09cf530d564aa75ab866a461c371345689d379cb57f9336f0fd2224bcd4cedd0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|