Skip to main content

Blocks secrets, credentials, and sensitive files from ever entering an AI coding agent's context window.

Project description

ctxguard

CI Python 3.9+ License: MIT

Your AI coding agent should never see your API keys.

ctxguard blocks secrets before they enter the model's context.

ctxguard is a local Claude Code plugin and standalone Python CLI. It intercepts sensitive tool calls before execution and returns a masked explanation instead of letting likely secrets, credentials, or sensitive files enter context.

30-second installation

Claude Code plugin (no Python package install)

Inside Claude Code, add this repository as a marketplace and install ctxguard:

/plugin marketplace add Ismail-Rhoulam/ctxguard
/plugin install ctxguard@ctxguard-plugins
/reload-plugins

The plugin includes its own Python source. It requires python3 3.9 or newer on PATH, but does not require pip install ctxguard.

For local development, run claude --plugin-dir . from this repository.

Standalone CLI

python3 -m pip install ctxguard
ctxguard init

ctxguard init creates .ctxguard.toml if absent and registers CLI-backed hooks in .claude/settings.json. If that settings file already exists, ctxguard asks before modifying it; non-interactive use requires the explicit --yes flag. It merges entries and preserves unrelated settings.

Why ctxguard?

Tool Primary protection
.gitignore Prevents selected files from being committed
Gitleaks / TruffleHog Detects secrets in repositories and commits
ctxguard Blocks sensitive content before an AI coding agent reads it

ctxguard complements repository scanners; it does not replace them. Gitleaks and TruffleHog protect repository history and workflows. ctxguard addresses a different boundary: the agent tool call immediately before content enters the model context.

How it works

Claude Code hooks can allow or deny a tool call, but cannot rewrite its result. ctxguard is therefore block-and-report, not silent redaction:

  1. A PreToolUse hook inspects Read, Edit, Write, Bash, Grep, and Glob inputs before execution.
  2. Sensitive filenames, small text-file contents, common shell reads, environment dumps, and inline high-confidence secrets are checked locally.
  3. In block mode, a flagged call is denied with a masked reason. In warn mode, it is allowed with warning context.
  4. A capped SessionStart scan tells Claude which files to avoid without returning their raw contents.

The CLI uses the same detector module as both plugin hooks.

Example blocked tool call

Claude Code attempts: Read .env
ctxguard intercepts: PreToolUse
Tool call result: DENIED
Explanation: ctxguard blocked this Read call: .env is a sensitive file by name
Raw values printed: no

Run the synthetic demonstration with python3 scripts/demo.py. See docs/demo.md for details and safe GIF-recording instructions.

What it detects

  • AWS access key IDs and secret access keys
  • GitHub classic and fine-grained personal access tokens
  • Slack tokens
  • Stripe live and test secret keys
  • GCP API keys (AIza...) and service-account JSON (content marker plus the filename rule)
  • Azure storage, Service Bus, Event Hub, and IoT Hub connection string keys (AccountKey=..., SharedAccessKey=...)
  • Twilio API key SIDs and SendGrid API keys
  • OpenAI-style keys (sk-..., sk-proj-...) and Anthropic keys (sk-ant-...)
  • Database URLs with inline passwords: Postgres, MySQL/MariaDB (including SQLAlchemy dialect+driver and Rails mysql2:// schemes), MongoDB, Redis, AMQP, and MSSQL
  • private key blocks and JWT-shaped strings
  • credential-like assignments that pass length, digit, and entropy thresholds
  • high-entropy values assigned to names containing key, secret, token, password, or credential
  • sensitive filenames including .env, non-template .env.*, SSH keys, *.pem, *.pfx, credentials.json, and service-account*.json

Detection is heuristic and local. ctxguard makes no network calls and uses no telemetry or machine learning.

Configuration

Copy .ctxguard.toml.example to .ctxguard.toml, or run ctxguard init:

mode = "block" # or "warn"

allowlist = [
    "tests/fixtures/*",
]

[[custom_patterns]]
name = "acme_internal_token"
regex = "acme_[A-Za-z0-9]{32}"
confidence = "high"

Allowlisting suppresses detection and should be narrow. Custom regular expressions are applied alongside built-ins.

CLI

ctxguard scan               # scan current directory; exit 1 on findings
ctxguard scan path/ --json  # machine-readable masked report
ctxguard init               # create config and register Claude Code hooks
ctxguard doctor             # verify PATH resolution and hook registration
ctxguard --version

ctxguard doctor checks that the ctxguard executable resolves on PATH (what the hooks registered by ctxguard init actually invoke), that the resolved binary's version matches the one running the check, that .claude/settings.json has both hooks registered with the expected matcher, that .ctxguard.toml parses if present, and does an end-to-end smoke test by actually invoking the PreToolUse hook once. Exits 1 if anything is broken (--json for scripting), 0 if warnings only or fully healthy.

Honest limitations

  • Pattern and entropy matching has false positives and false negatives. A secret that resembles prose may pass; an unusual random value may be flagged.
  • ctxguard blocks calls; it cannot redact tool output in flight. If a detector misses sensitive content in a normal-looking file, that content can enter context.
  • The Bash parser is heuristic and cannot model every shell construction.
  • Filename checks intentionally deny some files without inspecting content.
  • Files over 1 MB and binary files are not content-scanned. Session scans are time- and file-capped for responsiveness.
  • Hook errors fail open so ctxguard cannot break a Claude Code session. This preserves availability but means a broken hook does not provide protection.
  • Native Windows compatibility is not claimed; current testing covers the Python package and hook contract on Unix-like CI runners.
  • Any non-placeholder password inline in a database URL is flagged, including weak or "demo" ones (hunter2, letmein123). This is intentional: a weak credential is still a working credential, and ctxguard can't judge which ones are safe to expose. Allowlist known-safe fixtures in .ctxguard.toml instead.
  • GCP AIza...-style API keys are flagged even though some (notably Firebase web config keys) are designed to be usable client-side. Restrict such keys by API and referrer in the Google Cloud Console rather than relying on ctxguard to tell intent apart; allowlist the specific file if it's noisy.
  • A handful of well-known, publicly documented development constants (e.g. the Azurite/Azure Storage Emulator default key) are excluded by name since they're identical on every machine and not secrets. This list is small and only grows for equally unambiguous cases.

Use layered controls: least-privilege credentials, a secrets manager, .gitignore, repository secret scanning, short-lived tokens, and revocation.

Security model

ctxguard trusts the local Python runtime, Claude Code's hook execution, the installed plugin files, and project configuration. Detection and reporting stay on the local machine. Reports contain masked matches, filenames, categories, and line numbers, never intentionally the full matched value.

An attacker who can alter the plugin, configuration, interpreter, hook input, or files between inspection and execution may bypass it. ctxguard is a preventive guardrail, not a sandbox, secrets manager, or formal non-disclosure guarantee. See SECURITY.md for private reporting guidance.

Development

python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/pytest
.venv/bin/python -m build
.venv/bin/twine check dist/*

Test the plugin locally with claude plugin validate . and claude --plugin-dir .. Fixtures containing detector-positive synthetic values are confined to tests/fixtures/ and allowlisted by the repository example configuration.

Contributing

Issues and pull requests are welcome. Detector changes must include positive and negative tests, and outputs must never reveal an unmasked match. Keep the project local, dependency-light, auditable, and honest about limitations. Run the complete test suite before submitting. See SECURITY.md for security reports rather than opening a public bypass report.

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

ctxguard-0.1.0.tar.gz (35.0 kB view details)

Uploaded Source

Built Distribution

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

ctxguard-0.1.0-py3-none-any.whl (23.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: ctxguard-0.1.0.tar.gz
  • Upload date:
  • Size: 35.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ctxguard-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d46ff301772d44ee824c9d143146d8cf7b165c2a3b0e0e6058b7b55d93a8483b
MD5 2fa256b038f7cced43546e7851d8fcf2
BLAKE2b-256 d0beb1d98d91ab80d08b08f647e10c946f44c53044d878928f8517f075b572ae

See more details on using hashes here.

Provenance

The following attestation bundles were made for ctxguard-0.1.0.tar.gz:

Publisher: publish.yml on Ismail-Rhoulam/ctxguard

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

File details

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

File metadata

  • Download URL: ctxguard-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 23.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ctxguard-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 59164662f3adbb976c74b4647cf440e6f25ba48a5c670d9586bd4f2fbc6e2606
MD5 86c21191cf5d65f5ae501a68a40bb7d1
BLAKE2b-256 be817f64336cf66d2827734d2e8a1aa0bcb18dd2c6c95295d5fe9597ddcee4fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for ctxguard-0.1.0-py3-none-any.whl:

Publisher: publish.yml on Ismail-Rhoulam/ctxguard

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