ReproGuard is a pre-flight inspection for Jupyter notebooks, Python scripts, and ML repos. It finds the risks that survive review — leakage, secrets in outputs, unpinned environments, out-of-order cells, unchecked agent tools — then gives you a score you can gate on.
# one install, no config required
$ pip install reproguard
$ reproguard scan .
Python 3.10+ runs entirely offline nothing leaves the machine
A notebook can be syntactically perfect, pass review, and still be impossible to rerun — or worse, leak data it was never supposed to see. These are the six failures we see most often in the lab.
Test-set statistics bleed into training. The metric looks excellent and the model collapses in production. ReproGuard reads call order and flags it as critical.
Execution counts that aren't monotonic mean the saved state doesn't match top-to-bottom code. Rerun it and you get different numbers, or a NameError.
Notebook outputs are committed alongside code. API keys, customer emails, and tracebacks stay in the file long after they scroll off screen.
No requirements file, or pip install pandas inside a
cell. Both resolve to whatever is newest on install day.
C:\Users\… and /Users/… work on exactly
one machine. The next person opens the repo and stops.
Tools that shell out, model ids that aren't pinned, missing timeouts, prompts that interpolate untrusted input. Caught statically — no API keys required.
Agent → tool(shell=True) · model="gpt-4o" → pin the model, sandbox the tool
If ReproGuard can't parse a cell (non-Python kernel, IPython magic, corrupt JSON), it stays silent. A wrong finding costs more trust than a missing one.
Every finding carries a code, severity, confidence, the exact evidence line, and a fix you can apply. The score is a published penalty formula — severity weight times class weight — so you can recompute it by hand.
| Class | What it catches | Range |
|---|---|---|
| Reproducibility | Missing or unpinned dependency files, no random seeds, out-of-order execution, stale outputs, syntax errors, unpinned Docker base images | Low → Critical |
| Data leakage | Preprocessing before split, target-like feature columns, test data in fit calls, suspiciously high metrics, tracebacks and data dumps in output | Low → Critical |
| Privacy & security | Emails, phone and card numbers, AWS keys, hardcoded secrets, private keys, high-entropy credentials, credentials in URLs and connection URIs | Low → Critical |
| Data dependency | Local machine paths, referenced data files that don't exist, hardcoded paths in notebook output, large artifacts committed to git | Medium → High |
| GenAI | LLM client configuration, prompt injection bait, untrusted interpolation, LangGraph and CrewAI agent structure, tool agency, system-prompt leakage | Low → Critical |
| Handoff readiness | Missing objective, data source, assumptions, or metric documentation; uncommitted changes at scan time | Low |
| Execution | Notebook execution failures and kernel or dependency setup errors on a clean kernel run | High → Critical |
Scoring:
penalty = Σ severity × (weight/20) × confidence · Score =
100 − penalty. Critical on any file caps the status at
not ready.
Start permissive. Tighten as the debt comes down. The log tells you when a stricter gate is realistic.
Point it at one file or a directory. ReproGuard walks the tree once, picks up the nearest dependency files, and analyses each file notebook cell by cell, including the outputs. No config needed for the first run.
Every issue is explainable: the code, why it triggered, the
evidence line, and the fix. Suppress false positives per-path with
checks.ignore rather than muting whole classes.
--fail-under blocks on an absolute score.
--baseline with --fail-new blocks only
on regressions, so existing debt can be paid down gradually
instead of all at once.
reproguard scan . --baseline .reproguard/reproguard-report.json
--fail-new 0
exit 1 only on new findings
These are not mockups. Each card below is a live
reproguard scan report. Open the demo to filter by
severity, expand any finding, and read the code that triggered it
side-by-side with the source.
ReproGuard has no server, no account, and no telemetry. It is a CLI that returns a meaningful exit code and speaks the formats your tooling already understands.
GitHub Actions and GitLab CI, a reusable composite action, a pre-commit hook, or a plain local run before you push. SARIF uploads straight into GitHub Code Scanning. Works on Linux, macOS, Windows.
Color-coded terminal summary, JSON, standalone interactive HTML,
SARIF 2.1.0, and a GitLab Code Quality report. Stream to stdout
with -f json -o - and pipe to jq.
Checks stay silent on code the tool cannot understand — non-Python kernels, IPython magics, corrupt notebooks. A finding you have to argue with is worse than no finding.
Tune severity penalties and class weights, disable individual
checks, scope suppression by path and evidence regex, or add your
own regex rules in .reproguard.yml.
One pip install. Add a config only when a finding turns out to be wrong — and even then, per-path, not per-project.
pip install reproguard
· reproguard scan .
· Python 3.10+