Skip to main content

ReproGuard

Python License Ruff Status

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.txt or 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

  1. Local-first โ€” Scans run entirely on your machine. No data or notebooks leave your environment.
  2. Explainable rules โ€” Every issue has a code, severity, evidence, confidence score, and suggested fix. No black boxes.
  3. Low friction โ€” CLI-first design with a single reproguard scan <target> command. Pre-commit hook, CI integration, and GitHub Action out of the box.
  4. Conservative scoring โ€” The score is transparent (penalty-based, weighted by severity and category). You can customize all penalties and weights.
  5. 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.ignore to 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

reproguard-0.2.0.tar.gz (248.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

reproguard-0.2.0-py3-none-any.whl (48.2 kB view details)

Uploaded Python 3

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

Hashes for reproguard-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5fa78fea1ed079e3c006a6068cff8edc8bc7c7fd14ff901ef38392663ce37eae
MD5 55043f44f11926124d47e390af3b9142
BLAKE2b-256 738b65c274346d85474e85d15c91f70c603aef56b7e8c2961831d904da3aece3

See more details on using hashes here.

Provenance

The following attestation bundles were made for reproguard-0.2.0.tar.gz:

Publisher: release.yml on vipulgote1999/ReproGuard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for reproguard-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 00626a51e36968be4ef20a41f68fbfb9ce3684ad0470555575b19734d75e5de5
MD5 31a8123f5ee94464a8bd604cea426301
BLAKE2b-256 fa88a6abcbf658655f3d5023ecdc459b5ce3156bfe921e92a92e7b6d13473ae7

See more details on using hashes here.

Provenance

The following attestation bundles were made for reproguard-0.2.0-py3-none-any.whl:

Publisher: release.yml on vipulgote1999/ReproGuard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page