Skip to main content

Detect silent failures and unexpected runtime side effects during development and CI.

Project description

SilentGuard

pip install silentguard — detect silent failures and unexpected runtime side effects during local development and CI.

Python 3.11+ License: MIT


The Problem

Developers often catch exceptions too broadly, suppress failures unintentionally, or trigger hidden side effects — global state mutation, file I/O, network calls, subprocess execution, environment changes. These issues are hard to spot in tests and code review.

SilentGuard surfaces these behaviours with clear, actionable runtime reports.

Quick Start

pip install silentguard

As a Decorator

from silentguard import guard

@guard()
def process_data():
    try:
        result = risky_operation()
    except Exception:
        pass  # SilentGuard flags this
    
    os.environ["API_KEY"] = "secret"  # flagged

As a Context Manager

from silentguard import guard

with guard(report_format="markdown", output_path="report.md") as session:
    do_something_risky()

print(f"Detected {len(session.events)} events")

CLI — Run Under Instrumentation

# Run a script with full instrumentation
silentguard guard my_script.py

# Run a module
silentguard guard my_package.module

# Hide LOW-confidence noise
silentguard guard my_script.py --min-confidence medium

# Lower overhead (disable trace hook)
silentguard guard my_script.py --no-trace

CLI — Static Audit

# Scan a file
silentguard audit app.py

# Scan a directory
silentguard audit src/

# Output as HTML
silentguard audit src/ --format html --output audit.html

CLI — Run Tests

# Run pytest with SilentGuard
silentguard test

# With pytest args
silentguard test -- -x -v tests/

# With report format
silentguard test --format markdown --output test_report.md

# Reduce noise and fail CI on actionable findings
silentguard test --min-confidence medium --fail-on high

pytest Integration

# Directly with pytest (plugin auto-discovered)
pytest --silentguard

# With format options
pytest --silentguard --sg-format=html --sg-output=report.html

What It Detects

Category Detection Method Confidence
Suppressed exceptions sys.monitoring (3.12+) or sys.settrace fallback (3.11) HIGH for broad except Exception, MEDIUM for specific types, skips control-flow (StopIteration, etc.)
File I/O sys.addaudithookopen events HIGH for writes, MEDIUM for reads
Network calls sys.addaudithooksocket.connect, socket.getaddrinfo HIGH
Subprocess execution sys.addaudithooksubprocess.Popen, os.system HIGH
Env variable mutation sys.addaudithookos.putenv, os.unsetenv HIGH
Thread spawning sys.addaudithook_thread.start_new_thread MEDIUM
Global state mutation AST analysis — global statements MEDIUM (audit only)

Static Audit (AST-based)

The audit command performs additional best-effort checks:

  • Bare except: clauses
  • Broad except Exception: with silent bodies (pass / ...)
  • Calls to exec(), eval(), os.system(), subprocess.*
  • global statements indicating module state mutation
  • Imports of networking modules (socket, requests, etc.)

Output Formats

Format Use Case
terminal Interactive development (default, Rich-powered)
markdown Issue trackers, PR comments, postmortems
html Self-contained single-file reports for sharing
sarif GitHub Code Scanning / CI pipelines

Project Configuration

SilentGuard auto-discovers a .silentguardrc file by walking up from the current working directory. This lets a project tune noise levels and ignore known-benign patterns without changing application code.

[runtime]
detect_asyncio = true

[allow]
files = ["*.log", "*/.pytest_cache/*"]
network_hosts = ["localhost"]

[filters]
min_confidence = "medium"
ignore_file_patterns = ["*/vendor/*"]
ignore_function_patterns = ["legacy_*"]

[categories]
disabled_events = ["thread_spawn"]
disabled_scan = ["bare_except"]

CLI flags override config values when you need a one-off run:

silentguard guard app.py --min-confidence high
silentguard audit src/ --min-confidence medium
silentguard test --min-confidence medium --fail-on high

CI / Code Scanning

# Emit SARIF for GitHub Code Scanning or other CI integrations
silentguard ci src/ --output silentguard.sarif --fail-on high

The repository also includes a GitHub Actions workflow in .github/workflows/silentguard.yml that runs both static audit and pytest instrumentation and uploads SARIF results.

Configuration

All detection categories can be toggled:

from silentguard import guard

@guard(
    detect_suppressed_exceptions=True,   # default: True
    detect_file_io=False,                # disable file I/O detection
    detect_network=True,
    detect_subprocess=True,
    detect_env_mutation=True,
    detect_threading=True,
    report_format="markdown",
    output_path="report.md",
    allowed_file_patterns=[".log", "/tmp/"],  # ignore these paths
    allowed_network_hosts=["localhost"],       # ignore these hosts
)
def my_function():
    ...

Runtime reports automatically drop SilentGuard internals and stdlib/importlib-only frames from stack summaries so common interpreter noise does not dominate output.

Architecture

silentguard/
├── __init__.py          # Public API
├── __version__.py       # Version metadata
├── core.py              # GuardSession + SourceScanner
├── decorators.py        # @guard() decorator / context manager
├── hooks.py             # sys.addaudithook + sys.settrace management
├── reporter.py          # Terminal / Markdown / HTML formatters
├── cli.py               # Click CLI
├── pytest_plugin.py     # pytest plugin (auto-discovered)
└── utils.py             # Shared data structures and helpers

Limitations & Known Issues

By Design

  • Best-effort diagnostics, not a formal verifier. SilentGuard uses runtime heuristics. It will miss some issues and may flag intentional behaviour.
  • Confidence levels are heuristic. A HIGH confidence event is not certain to be a bug — it means the structural pattern is commonly problematic.
  • sys.addaudithook is permanent. Once installed, CPython audit hooks cannot be removed for the lifetime of the process. SilentGuard minimises impact with a fast no-op guard when inactive.
  • Tracing adds overhead. On Python 3.11, suppressed-exception detection uses sys.settrace; on 3.12+, SilentGuard uses sys.monitoring fast-path where available and falls back to sys.settrace.

Overhead Benchmarks (pyperf)

Measured on Python 3.13 (Windows laptop), workload: 1000 pure-Python function calls (benchmarks/workload.py), with and without instrumentation.

  • Baseline (no instrumentation): ~3.97 ms
  • SilentGuard with sys.monitoring: ~6.48 ms (about 1.6x baseline)
  • SilentGuard forced sys.settrace: ~418.97 ms (about 105x baseline)

For this workload, sys.monitoring is roughly 65x faster than sys.settrace (418.97 / 6.48).

Detection Limits

  • Suppressed exceptions: Cannot distinguish between intentional handling (e.g. try: d[k] except KeyError: default) and genuine suppression. Mitigated by confidence levels.
  • Global state mutation at runtime: Not detected beyond environment variables. The AST scanner catches global statements but cannot track arbitrary attribute mutations.
  • Asyncio side effects: Limited to thread-spawning detection. Full coroutine-level instrumentation is out of scope for v1.
  • Indirect network calls: Calls through C extensions or FFI that bypass Python's socket layer are invisible to audit hooks.
  • File I/O noise: Python's own import machinery triggers open events. SilentGuard filters .pyc/.pyo/.so files and its own internals, but some noise may remain.

Platform & Version

  • Requires Python 3.11+.
  • sys.addaudithook is available since Python 3.8.
  • sys.settrace behaviour may vary between CPython versions; not supported on alternative interpreters (PyPy, GraalPy).

Development

# Clone and install in editable mode
git clone https://github.com/your-org/silentguard.git
cd silentguard
pip install -e ".[dev]"

# Run tests
pytest

# Run with SilentGuard's own plugin
pytest --silentguard

# Type checking
mypy src/

# Linting
ruff check src/ tests/

# Benchmarks
pip install pyperf
python benchmarks/pyperf_silentguard.py

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

silentguard-0.1.0.tar.gz (63.6 kB view details)

Uploaded Source

Built Distribution

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

silentguard-0.1.0-py3-none-any.whl (31.2 kB view details)

Uploaded Python 3

File details

Details for the file silentguard-0.1.0.tar.gz.

File metadata

  • Download URL: silentguard-0.1.0.tar.gz
  • Upload date:
  • Size: 63.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for silentguard-0.1.0.tar.gz
Algorithm Hash digest
SHA256 87a2aa3a48880c566ff5ceea7c534fc610e3bc5f26f7beec79b071edfc16f0fe
MD5 b2434a00d57e91f72f372274f445ddbb
BLAKE2b-256 26a7e5e3bc7c30568e85daac95c9eb7bd16c04e4aee567bd2ddaab741b04b2e4

See more details on using hashes here.

File details

Details for the file silentguard-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: silentguard-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 31.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for silentguard-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 abb69e7a0760e888637edfb01e950016eb38e706c1128d6db38b122c6ad7048b
MD5 8cd8d8d5ddf422556c89631f53e0da40
BLAKE2b-256 6542ae8e28bf0373922cb16b146c9d047937824376dcbd46b2e843f82016b19a

See more details on using hashes here.

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