This guide shows how to wire sanctifier zk lint and sanctifier verify-circuit into an existing circom + snarkjs or Noir project's development workflow and CI pipeline.
See also: INTEGRATION-GUIDE.md for generic SARIF pipeline patterns and zk-security-guide.md for a reference on ZK vulnerability classes.
- What Sanctifier checks in ZK circuits
- Installation
- circom + snarkjs workflow
- Noir workflow
- CI integration
- Interpreting results
- Z-rule reference
Sanctifier applies its Z-rules (Z001–Z014) to ZK circuits and their on-chain verifiers:
| Rule | Finding | Severity |
|---|---|---|
| Z001 | Missing nullifier / double-spend check | critical |
| Z002 | Insecure or predictable randomness as circuit input | high |
| Z003 | Missing public-input binding (proof malleability) | critical |
| Z004 | Unverified trusted-setup parameters | critical |
| Z005 | Missing verifying-key integrity check | high |
| Z006 | Missing proof nonce / uniqueness enforcement | high |
| Z007 | Under-constrained circuit inputs | critical |
| Z008 | Curve / field mismatch | critical |
| Z009 | Unbounded proof-verification loop (DoS) | high |
| Z010 | Verifying-key rotation without access control | critical |
| Z011 | Commitment reuse without domain separation | high |
| Z012 | ZK property leak via public-output over-exposure | medium |
| Z013 | Insufficient batch-validation in ZK-rollup transitions | critical |
| Z014 | Missing Merkle-root inclusion-proof verification | critical |
The canonical catalogue lives in
docs/rules/(Z001.md–Z014.md) and is mirrored bydata/vulnerability-db.jsonanddata/sarif/rule-metadata.yaml. See zk-roadmap.md for which of these ship as implemented rules today.
# Install the CLI (no Z3 required for ZK rules)
cargo install sanctifier-cli --locked --no-default-features
# Verify
sanctifier --versionmy-circom-project/
├── circuits/
│ ├── main.circom
│ └── lib/
│ └── helpers.circom
├── contracts/
│ └── Verifier.sol # generated by snarkjs
├── scripts/
│ └── compile.sh
└── package.json
# Lint all .circom sources; print findings as text
sanctifier zk lint circuits/ --toolchain circom
# Raise the bar: fail on medium+ findings
sanctifier zk lint circuits/ --toolchain circom --min-severity medium --exit-code
# Output SARIF for IDE / GitHub Code Scanning
sanctifier zk lint circuits/ --toolchain circom --format sarif > zk-results.sarif# Fail if the compiled circuit exceeds 50 000 R1CS constraints
sanctifier verify-circuit circuits/main.circom \
--toolchain circom \
--max-constraints 50000{
"scripts": {
"lint:zk": "sanctifier zk lint circuits/ --toolchain circom --exit-code",
"verify:circuit": "sanctifier verify-circuit circuits/main.circom --toolchain circom"
}
}my-noir-project/
├── src/
│ └── main.nr
├── Nargo.toml
└── Prover.toml
sanctifier zk lint src/ --toolchain noir
sanctifier zk lint src/ --toolchain noir --min-severity medium --exit-code
sanctifier zk lint src/ --toolchain noir --format sarif > zk-results.sarifsanctifier verify-circuit src/main.nr --toolchain noirCopy the ready-to-use workflow from docs/integration-examples/zk-circom-noir.yml into your .github/workflows/ directory.
It contains two jobs — one for circom/snarkjs and one for Noir — both of which:
- Install the Sanctifier CLI and the relevant ZK toolchain.
- Run
sanctifier zk lintand write SARIF output tosanctifier-zk.sarif. - Run
sanctifier verify-circuitfor constraint-count validation. - Upload the SARIF file to GitHub Code Scanning with
github/codeql-action/upload-sarif.
The || true on the lint step keeps the upload step reachable even when findings are present; set --exit-code and remove || true once you have resolved existing findings.
[Z009] HIGH contracts/Verifier.sol:42 Unbounded proof-verification loop
→ batch_claim iterates proofs.length without a size cap; cap at a safe constant.
Findings appear in the Security → Code scanning tab. Each finding links to the rule's helpUri (e.g. https://docs.sanctifier.dev/rules/Z009) for remediation guidance.
Full rule documentation lives in docs/rules/Z001.md … docs/rules/Z014.md.
Quick summaries are in the table above; SARIF metadata is in data/sarif/rule-metadata.yaml.