Skip to main content

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-78 is 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.
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 app vs build-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 (see schemas/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.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vulngate 1.5.5
File Size Uploaded
vulngate-1.5.5.tar.gz 61.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vulngate 1.5.5
File Interpreter ABI Platform
vulngate-1.5.5-py3-none-any.whl Python 3 none any Details

Total release size: 102.8 kB

Release files / vulngate-1.5.5.tar.gz

Download URL vulngate-1.5.5.tar.gz
Size 61.1 kB
Tags Source
SHA-256 checksum
How to use checksums
e9faeb9623e7d6d5469fc4fc29378f3f572a427f86c857bc4d8389aa85da0243
BLAKE2b-256 checksum
How to use checksums
ffb6afff1d74383738ca5c6c1ce25ff5c07996e7d90bf293a94b7c22fcc9769f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / vulngate-1.5.5-py3-none-any.whl

Download URL vulngate-1.5.5-py3-none-any.whl
Size 41.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
581708176d89fc73f871a03bd7952edd14dbda7a6ad3593ecd407ad5881cf075
BLAKE2b-256 checksum
How to use checksums
17e283decbfe3f9bd646dd6cc6aa813d26b0688bd6be1f8cb221be957039bb8d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release history Release notifications | RSS feed

This release

1.5.5 This release

2 release files

1.5.4

2 release files

1.5.3

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page