Linters check that code compiles. PrufGate looks for code that compiles, passes review at a glance and still does not do the job. This is the kind of code an AI coding agent (or a hurried human) writes to make a task look finished:
- a
catchblock that returns a hard-coded success object; - a click handler that does nothing;
- a test that asserts
true, or mocks the very function it tests; - a
.skip,@ts-ignoreor lowered coverage threshold slipped into a diff; - an import of a package that is not declared anywhere;
- an API route that loads a record by ID without checking who owns it.
PrufGate is deterministic: plain Python, no network calls and no LLM unless you ask for one. It runs in seconds on a pull request, and writes SARIF for code scanning and Markdown for humans. It is meant to sit next to your linters and SAST tools, not replace them.
The six engines
| # | Engine | What it catches |
|---|---|---|
| 1 | Anti-fabrication (prufgate/anti_fabrication) |
Canned success on error paths, simulated return values, MOCK_*/SAMPLE_* data in production code, stub UI handlers, fake "fresh" timestamps, unimplemented stubs, LLM prompts that ask for a verdict without passing any evidence, documentation addresses in production. |
| 2 | Test integrity (prufgate/anti_reward_hacking) |
Tests with no assertions, assertions that cannot fail, tests that mock the unit under test, swallowed exceptions, assertions deleted or weakened in a diff, production code special-casing a test's literal input. |
| 3 | Diff guard (prufgate/diff_guard) |
Skips and focus (.skip, .only, xit, pytest.mark.skip, t.Skip(), #[ignore], @Disabled) added without an issue reference, bare suppressions (@ts-ignore, # noqa, // nolint, #[allow]), as unknown as T casts, weakened linter/CI/coverage settings, and new exemptions in PrufGate's own config. |
| 4 | Contract guard (prufgate/contract_guard) |
Imports not declared in package.json, pyproject.toml/requirements*.txt, go.mod or Cargo.toml; environment variables read without a default and missing from .env.example; frontend calls to API routes that do not exist. |
| 5 | BOLA / IDOR (prufgate/bola) |
Route handlers that look up a record by a client-supplied ID with no auth guard or no tenant/owner scoping, across Express, Next.js, NestJS, FastAPI, Flask, Django, Go (net/http, Gin, Echo, Chi), Spring, Rails and Laravel. Optional live two-token probing of a running service you own. |
| 6 | Diff reviewer (prufgate/review) |
High-precision rules on changed lines (SQL built from strings, shell injection, disabled TLS verification, hard-coded credentials, unsanitised HTML, ignored Go errors, credential logging), GitHub suggestion blocks, and optional delegation to an AI CLI or API you choose. |
Details, rule IDs, supported languages and known limits for each engine: docs/ENGINES.md.
PrufGate uses pattern and structure heuristics, not a full parser for every language. It will miss things and it will sometimes flag correct code. Every finding names its rule, and inline prufgate-ignore comments, exemptions and baselines let you record why.
Quick start
PrufGate needs Python 3.9 or newer and Git.
pipx install prufgate # or: pip install prufgate (the `prufgate` and `prufgate-mcp` commands)
prufgate --self-check # every engine against its built-in fixtures
Or run the signed container image, which adds the full gate with ast-grep, gitleaks and zizmor:
docker run --rm -v "$PWD:/workspace" ghcr.io/guardianvigil-labs/prufgate:1.0.0 # the fast gate on this repository
docker run --rm -v "$PWD:/workspace" ghcr.io/guardianvigil-labs/prufgate:1.0.0 prufgate check .
Or add the GitHub Action to a pull-request workflow, pinned to the commit SHA of the v1.0.0 tag (full example):
- uses: actions/checkout@<commit-sha>
with: { fetch-depth: 0, persist-credentials: false }
- run: python3 -m pip install "PyYAML>=6.0"
- uses: GuardianVigil-Labs/Prufgate@<commit-sha-of-v1.0.0>
Every release is signed and carries build provenance and an SBOM: Verify a release.
Then, in your project:
prufgate check . # engines 1-5 on the whole repository
prufgate check --changed --base origin/main # only what this branch changed
prufgate init --hooks # starter config + coding-agent hooks
Exit codes are the same everywhere: 0 clean, 1 blocking findings (P0/P1), 2 PrufGate could not run (bad config, bad base ref, unreadable file, engine crash). A crash never reads as a pass.
Ways to run it
| Want | Use |
|---|---|
| A quick check while coding | prufgate check --changed |
| One engine | prufgate test-audit, prufgate bola, prufgate review |
| The full gate with SARIF and Markdown reports | ./prufgate.sh fast (changed files) or ./prufgate.sh full, from a checkout. Reports go to reports/prufgate.sarif and reports/prufgate-review.md. |
| A pull-request gate on GitHub | The composite action in this repository: docs/CI_INTEGRATION.md |
| A coding agent sent back to fix its findings before it stops | prufgate init --hooks (Claude Code Stop hook, which asks once; Cursor rule; the pre-commit hook and the CI gate enforce) |
| Tools for an agent over MCP | prufgate mcp: nine read-only tools |
| A service that scans on webhook | prufgate api: bearer token, loopback by default |
The full command and option reference is in docs/GETTING_STARTED.md, and every configuration key is in docs/CONFIGURATION.md.
Configuration in one look
PrufGate works without configuration. To tune it, add .prufgate/config.yaml:
version: 1
packs: [core, web-ui, ai-safety] # cti is an opt-in domain pack
exclude: ["dist/**", "vendor/**"]
auth_guards: [requireUser, get_current_user]
tenant_keys: [organization_id, account_id]
exempt:
src/legacy/adapter.ts:
route-canned-fallback: "#104: legacy fallback until the payments API migration"
known_debt:
stub-click-handler: 0 # a ceiling that can only go down
Documentation
- Getting started: install, commands, reports, exit codes
- Configuration reference: every key, suppressions, environment variables
- The engines: rules, languages and limits
- CI and agent integration: GitHub Action, other CI, agent hooks, MCP, REST API
- Custom rules: your own ast-grep rules and hooks
- Architecture
- Changelog
Contributing and security
Contributions are welcome: see CONTRIBUTING.md and the maintainer guide AGENTS.md. Please report vulnerabilities privately, as described in SECURITY.md.
PrufGate is published by GuardianVigil under the Apache License 2.0. The name and logo are trademarks: see TRADEMARKS.md.
Metadata
Release files for prufgate 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| prufgate-1.0.0.tar.gz | 205.8 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| prufgate-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 368.4 kB
Release files / prufgate-1.0.0.tar.gz
| Download URL | prufgate-1.0.0.tar.gz |
|---|---|
| Size | 205.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
397b50d18f8cbbb26aa93d145611c332697937040822a035a546f2a3eadb40f8
|
|
BLAKE2b-256 checksum How to use checksums |
1518635e86c7a23b315fada42e4929f99a9181a9872649fe75b4c9d1d9d80047
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logRelease files / prufgate-1.0.0-py3-none-any.whl
| Download URL | prufgate-1.0.0-py3-none-any.whl |
|---|---|
| Size | 162.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5844be21ee95e08f606d8b5d399f35d8cfe88f74cb1beb7036b7115c35c270a7
|
|
BLAKE2b-256 checksum How to use checksums |
a72d62d5763651e98bd345ed7ffa59739a76f91e99703d9a4613050b604cc228
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logSecurity for prufgate 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for prufgate-1.0.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 25, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.