ReproGuard
Pre-production risk scanner for data science notebooks and ML repositories.
ReproGuard analyzes Jupyter notebooks and Python scripts for reproducibility risks, data leakage, privacy violations, missing dependencies, and handoff readiness โ before you share, review, or promote work toward production.
Positioning: SonarQube-style review for data science work. Not a replacement for MLflow, DVC, Databricks, DataHub, or data observability platforms.
Why This Exists
Data science projects often work on the author's machine but fail during review or production handoff because of:
- ๐ Local data paths โ
C:\Users\...or/Users/...that don't exist on another machine - ๐ฆ Missing dependencies โ No
requirements.txtor unpinned packages causing environment drift - ๐ Out-of-order execution โ Notebook cells run in a non-linear order, hiding stateful assumptions
- ๐ Hidden PII & secrets โ Email addresses, API keys, or credentials buried in code or output
- ๐ Data leakage โ Preprocessing before train/test split, test data in fit calls, target-like features
- ๐ Missing handoff docs โ No clear statement of objective, data source, assumptions, or instructions
ReproGuard is local-first โ scans happen on your machine without uploading data or notebooks to any third-party service.
Features
Detects 29 risk patterns across 6 categories
| Risk Category | What It Catches | Severity Range |
|---|---|---|
| Reproducibility | Missing dependency files, unpinned packages, no random seeds, out-of-order execution, stale outputs | LOW โ HIGH |
| Data Leakage | Preprocessing before split, target-like feature columns, test data in fit calls, suspiciously high metrics, tabular data dumps, output tracebacks | LOW โ CRITICAL |
| Privacy & Security | Email addresses, phone numbers, credit card numbers, AWS keys, hardcoded secrets, private key blocks, high-entropy credentials, base64 images, JSON blobs | LOW โ CRITICAL |
| Data Dependency | Local machine paths, missing referenced data files, hardcoded paths in output | MEDIUM โ HIGH |
| Handoff Readiness | Missing objective, data source, assumptions, or metric documentation | LOW |
| Execution | Notebook execution failures, kernel/dependency setup errors | HIGH โ CRITICAL |
Output Formats
- Terminal โ Color-coded summary with severity breakdown
- JSON โ Structured data for programmatic consumption
- HTML โ Styled standalone report with issue grouping
- SARIF 2.1.0 โ Compatible with GitHub Code Scanning and VS Code
Scoring
Penalty-based scoring from 0โ100. Status: ready_with_caution (โฅ75), needs_review (50โ74), or not_ready (<50 or any CRITICAL issue). All penalties and weights are configurable.
Installation
pip install reproguard
From source
git clone https://github.com/vipulgote1999/ReproGuard.git
cd ReproGuard
pip install -e .
Development install
pip install -e .[dev]
Privacy extra (Presidio support โ future)
pip install reproguard[privacy]
Quick Start
Scan a single notebook:
reproguard scan examples/risky_customer_churn.ipynb
Scan an entire project directory:
reproguard scan .
Scan with HTML report and fail CI on low score:
reproguard scan . --format html --fail-under 50
Enable clean notebook execution:
reproguard scan notebook.ipynb --execute
Usage Examples
Basic scan
reproguard scan examples/risky_customer_churn.ipynb
Output:
ReproGuard score: 27/100 (not_ready)
Files scanned: 1 | Issues: 8
Critical: 1 | High: 3 | Medium: 2 | Low: 2
Severity Code Issue Location
โโโโโโโโ โโโโ โโโโโ โโโโโโโโ
CRITICAL LEAK001 Possible preprocessing beforeโฆ risky_customer_churn.ipynb:cell 6
HIGH DATA001 Local machine path detected risky_customer_churn.ipynb:line 2
HIGH LEAK002 Future/target-like column namโฆ risky_customer_churn.ipynb:cell 4
HIGH LEAK007 Exception traceback found inโฆ risky_customer_churn.ipynb:cell 9
MEDIUM PII001 Email address detected risky_customer_churn.ipynb:cell 8
MEDIUM REP001 Non-deterministic code withoโฆ risky_customer_churn.ipynb:cell 6
LOW NB001 Notebook cells were executedโฆ risky_customer_churn.ipynb
LOW NB002 Notebook output exists withoโฆ risky_customer_churn.ipynb:cell 9
Generate reports
# All report formats
reproguard scan . --format all
# JSON only
reproguard scan . --format json
# SARIF for GitHub Code Scanning
reproguard scan . --format sarif
# Custom output directory
reproguard scan . --output-dir scan-reports
CI integration
# Fail the build if the score is too low
reproguard scan . --fail-under 50
echo $? # Exit code 1 when score < 50 or any CRITICAL issue
Regression detection (baseline diff)
Gate CI on new issues while existing debt is paid down gradually:
# First run: save the baseline
reproguard scan . --format json --output-dir .reproguard
# Later runs: block on new issues only
reproguard scan . --baseline .reproguard/reproguard-report.json --fail-new 0
reproguard scan . --baseline .reproguard/reproguard-report.json --fail-new-critical
New and resolved issues are printed in the terminal summary and recorded in the JSON report metadata. Exit codes: 1 when the gate trips, 2 for invalid baselines.
Scan with privacy disabled
reproguard scan . --no-privacy
Custom execution timeout
reproguard scan notebook.ipynb --execute --execution-timeout 300
Understanding Reports
Score interpretation
| Score | Status | Action Required |
|---|---|---|
| โฅ 75 | ready_with_caution |
Review minor issues before production |
| 50โ74 | needs_review |
Address significant issues |
| < 50 | not_ready |
Blocking issues โ must fix |
| Any CRITICAL | not_ready |
Immediate attention required |
| 0 files scanned | no_files |
No supported files found โ check the scan path (exit code 2) |
Report files
Reports are written to .reproguard/ by default:
.reproguard/
โโโ reproguard-report.json # Structured data
โโโ reproguard-report.html # Styled HTML report
โโโ reproguard-report.sarif # GitHub Code Scanning compatible
Configuration
Create a .reproguard.yml in your project root:
# .reproguard.yml
exclude_paths:
- "archive/**"
- "tests/**"
exclude_dirs:
- "scratch"
fail_under: 50
checks:
disabled:
- "LEAK005" # Disable large tabular output check
- "PII004" # Disable base64 image check
Configuration is discovered by walking up from the scan path (like git). See docs/CONFIGURATION.md for the full reference.
Pre-commit Hook
# .pre-commit-config.yaml
repos:
- repo: https://github.com/vipulgote1999/ReproGuard
rev: v0.2.0
hooks:
- id: reproguard-scan
args: ["--fail-under", "75"]
The hook scans the entire repository on each commit and blocks the commit when the score falls below the threshold.
CI/CD Integration
GitHub Actions (with SARIF upload)
name: ReproGuard
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install reproguard
- run: reproguard scan . --format sarif --fail-under 50
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: .reproguard/reproguard-report.sarif
GitLab CI
reproguard:
stage: test
script:
- pip install reproguard
- reproguard scan . --format html --fail-under 50
artifacts:
paths:
- .reproguard/
Project Structure
ReproGuard/
โโโ src/reproguard/
โ โโโ cli.py # Typer CLI entry point
โ โโโ scanner.py # Scan orchestrator
โ โโโ models.py # Core data models & scoring
โ โโโ config.py # .reproguard.yml loader
โ โโโ python_analysis.py # Python source analysis
โ โโโ leakage.py # ML data leakage heuristics
โ โโโ privacy.py # PII / secret scanning
โ โโโ notebook.py # Notebook parser
โ โโโ dependency.py # Dependency file analysis
โ โโโ execution.py # Clean notebook execution
โ โโโ report.py # JSON/HTML report generators
โ โโโ sarif.py # SARIF 2.1.0 report generator
โ โโโ plugin.py # Check registry & filtering
โ โโโ utils.py # Shared helpers
โโโ examples/
โ โโโ risky_customer_churn.ipynb # Notebook with intentional issues
โ โโโ clean_analysis.py # Clean script example
โ โโโ requirements.txt # Example dependency file
โโโ docs/
โ โโโ ARCHITECTURE.md # Internal design & module docs
โ โโโ CHECKS.md # Complete issue code reference
โ โโโ CONFIGURATION.md # Configuration file reference
โ โโโ GUIDES.md # Usage guides & integrations
โ โโโ ROADMAP.md # Future plans
โโโ pyproject.toml # Build & tool config
โโโ README.md # This file
Check Reference
| Code | Check | Severity | Category |
|---|---|---|---|
| PY001 | Python syntax error | CRITICAL | Reproducibility |
| DATA001 | Local machine path | HIGH | Data Dependency |
| DATA002 | Referenced data file not found | MEDIUM | Data Dependency |
| REP001 | Non-deterministic code without seed | MEDIUM | Reproducibility |
| LEAK001 | Preprocessing before train/test split | CRITICAL | Data Leakage |
| LEAK002 | Future/target-like column name | HIGH | Data Leakage |
| LEAK003 | Test data in fitting call | CRITICAL | Data Leakage |
| LEAK004 | Suspiciously high metric | MEDIUM | Data Leakage |
| LEAK005 | Large tabular output | LOW | Data Leakage |
| LEAK006 | Hardcoded path in output | MEDIUM | Data Dependency |
| LEAK007 | Exception traceback in output | HIGH | Reproducibility |
| PII001 | Email address | HIGH | Privacy |
| PII002 | Phone number | MEDIUM | Privacy |
| PII003 | Credit card number | HIGH | Privacy |
| PII004 | Base64 image in output | LOW | Privacy |
| PII005 | Large JSON/blob in output | LOW | Privacy |
| SEC001 | AWS access key | CRITICAL | Privacy |
| SEC002 | Hardcoded secret assignment | CRITICAL | Privacy |
| SEC003 | Private key block | CRITICAL | Privacy |
| SEC004 | High-entropy string | MEDIUM | Privacy |
| NB001 | Out-of-order execution | MEDIUM | Reproducibility |
| NB002 | Output without execution count | LOW | Reproducibility |
| NB003 | Non-default kernel requirement | MEDIUM | Reproducibility |
| DEP001 | No dependency file found | HIGH | Reproducibility |
| DEP002 | Unpinned dependency | LOW | Reproducibility |
| DEP003 | Imported package missing from deps | MEDIUM | Reproducibility |
| HAND001 | Missing handoff documentation | LOW | Handoff |
| EXEC001 | Notebook execution error | CRITICAL | Execution |
| EXEC002 | Execution setup failure | HIGH | Execution |
See docs/CHECKS.md for full details on every check.
Design Principles
- Local-first โ Scans run entirely on your machine. No data or notebooks leave your environment.
- Explainable rules โ Every issue has a code, severity, evidence, confidence score, and suggested fix. No black boxes.
- Low friction โ CLI-first design with a single
reproguard scan <target>command. Pre-commit hook, CI integration, and GitHub Action out of the box. - Conservative scoring โ The score is transparent (penalty-based, weighted by severity and category). You can customize all penalties and weights.
- Narrow wedge โ Focused on catching pre-production risks before work enters heavier MLOps pipelines.
Limitations
ReproGuard v0.1 (alpha) uses heuristics. It flags likely risks but cannot prove every issue is real. Treat it as a review assistant, not a final governance decision.
- Leakage detection is heuristic โ expect false positives (use
checks.ignoreto silence known-safe locations) - Dependency parsing is intentionally lightweight (regex-based for requirements/Pipfile, YAML for conda env files, TOML for pyproject/lock files โ no full resolver)
- Privacy scanning uses regex rules by default (Presidio support planned)
- Clean notebook execution depends on local kernel and dependency availability
- Data file existence checks are limited to paths referenced from notebooks/scripts
Development
# Install dev dependencies
pip install -e .[dev]
# Lint
ruff check .
# Test
pytest
# Build release artifacts and validate metadata
python -m build
python -m twine check dist/*
Releases follow the procedure in docs/RELEASING.md โ see the checklist there before tagging. Changes are tracked in CHANGELOG.md.
Roadmap
- v0.2 โ โ correctness hardening (magic handling, conda/lock dependency parsing), path-scoped ignore rules, baseline diffing, extended coverage
- v0.3: GitHub Action, custom rule engine, parallel notebook execution,
kernel-aware
--execute - v1.0+: ML pipeline scanning, differential scans, team dashboard, API
See docs/ROADMAP.md for the full roadmap.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file reproguard-0.2.0.tar.gz.
File metadata
- Download URL: reproguard-0.2.0.tar.gz
- Upload date:
- Size: 248.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5fa78fea1ed079e3c006a6068cff8edc8bc7c7fd14ff901ef38392663ce37eae
|
|
| MD5 |
55043f44f11926124d47e390af3b9142
|
|
| BLAKE2b-256 |
738b65c274346d85474e85d15c91f70c603aef56b7e8c2961831d904da3aece3
|
Provenance
The following attestation bundles were made for reproguard-0.2.0.tar.gz:
Publisher:
release.yml on vipulgote1999/ReproGuard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
reproguard-0.2.0.tar.gz -
Subject digest:
5fa78fea1ed079e3c006a6068cff8edc8bc7c7fd14ff901ef38392663ce37eae - Sigstore transparency entry: 2392357979
- Sigstore integration time:
-
Permalink:
vipulgote1999/ReproGuard@c99c641e8a9ed6aac9543adcf9e6c4c6ec6e2982 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vipulgote1999
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c99c641e8a9ed6aac9543adcf9e6c4c6ec6e2982 -
Trigger Event:
push
-
Statement type:
File details
Details for the file reproguard-0.2.0-py3-none-any.whl.
File metadata
- Download URL: reproguard-0.2.0-py3-none-any.whl
- Upload date:
- Size: 48.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00626a51e36968be4ef20a41f68fbfb9ce3684ad0470555575b19734d75e5de5
|
|
| MD5 |
31a8123f5ee94464a8bd604cea426301
|
|
| BLAKE2b-256 |
fa88a6abcbf658655f3d5023ecdc459b5ce3156bfe921e92a92e7b6d13473ae7
|
Provenance
The following attestation bundles were made for reproguard-0.2.0-py3-none-any.whl:
Publisher:
release.yml on vipulgote1999/ReproGuard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
reproguard-0.2.0-py3-none-any.whl -
Subject digest:
00626a51e36968be4ef20a41f68fbfb9ce3684ad0470555575b19734d75e5de5 - Sigstore transparency entry: 2392358226
- Sigstore integration time:
-
Permalink:
vipulgote1999/ReproGuard@c99c641e8a9ed6aac9543adcf9e6c4c6ec6e2982 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vipulgote1999
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c99c641e8a9ed6aac9543adcf9e6c4c6ec6e2982 -
Trigger Event:
push
-
Statement type: