Skip to main content

Prompt injection scanner CLI - substring, unicode, secrets, and ML detection

Project description

Parry-guard

Check Mentioned in Awesome Claude Code

Prompt injection scanner for Claude Code hooks. Scans tool inputs and outputs for injection attacks, secrets, and data exfiltration attempts.

Early development — this tool is under active development and may have bugs or false positives. Tested on linux/macOS.

Prerequisites

The ML models are gated on HuggingFace. Before installing:

  1. Create an account at huggingface.co
  2. Accept the DeBERTa v3 license (required for all modes)
  3. For full mode: also accept the Llama Prompt Guard 2 license (Meta approval required)
  4. Create an access token at huggingface.co/settings/tokens

Usage

Add to ~/.claude/settings.json:

With uvx:

{
  "hooks": {
    "PreToolUse": [{ "command": "uvx parry-guard hook", "timeout": 1000 }],
    "PostToolUse": [{ "command": "uvx parry-guard hook", "timeout": 5000 }],
    "UserPromptSubmit": [{ "command": "uvx parry-guard hook", "timeout": 2000 }]
  }
}

With rvx:

{
  "hooks": {
    "PreToolUse": [{ "command": "rvx parry-guard hook", "timeout": 1000 }],
    "PostToolUse": [{ "command": "rvx parry-guard hook", "timeout": 5000 }],
    "UserPromptSubmit": [{ "command": "rvx parry-guard hook", "timeout": 2000 }]
  }
}

With parry-guard on PATH (via Nix, cargo install, or release binary):

{
  "hooks": {
    "PreToolUse": [{ "command": "parry-guard hook", "timeout": 1000 }],
    "PostToolUse": [{ "command": "parry-guard hook", "timeout": 5000 }],
    "UserPromptSubmit": [{ "command": "parry-guard hook", "timeout": 2000 }]
  }
}
Other installation methods

From source:

# Default (ONNX backend - statically linked, 5-6x faster than Candle)
cargo install --path crates/cli

# Candle backend (pure Rust, no native deps, portable)
cargo install --path crates/cli --no-default-features --features candle

Nix (home-manager)

# flake.nix
{
  inputs.parry.url = "github:vaporif/parry";

  outputs = { parry, ... }: {
    # pass parry to your home-manager config via extraSpecialArgs, overlays, etc.
  };
}
# home-manager module
{ inputs, pkgs, config, ... }: {
  imports = [ inputs.parry.homeManagerModules.default ];

  programs.parry-guard = {
    enable = true;
    package = inputs.parry.packages.${pkgs.system}.default;  # onnx (default)
    # package = inputs.parry.packages.${pkgs.system}.candle;  # candle (pure Rust, portable, ~5-6x slower)
    hfTokenFile = config.sops.secrets.hf-token.path;
    ignoreDirs = [ "/home/user/repos/trusted" ];
    # askOnNewProject = true;  # Ask before monitoring new projects (default: auto-monitor)
    # claudeMdThreshold = 0.9;  # ML threshold for CLAUDE.md scanning (default 0.9)

    # scanMode = "full";  # fast (default) | full | custom

    # Custom models (auto-sets scanMode to "custom")
    # models = [
    #   { repo = "ProtectAI/deberta-v3-small-prompt-injection-v2"; }
    #   { repo = "meta-llama/Llama-Prompt-Guard-2-86M"; threshold = 0.5; }
    # ];
  };
}

Setup

1. Configure HuggingFace token

One of (first match wins):

export HF_TOKEN="hf_..."                          # direct value
export HF_TOKEN_PATH="/path/to/token"              # file path
# or place token at /run/secrets/hf-token-scan-injection

The daemon auto-starts on first scan, downloads the model on first run, and idles out after 30 minutes.

Note (non-Nix users): The Nix home-manager module wraps the binary with all config baked in via env vars. Without Nix, set env vars in your shell profile (e.g. HF_TOKEN, PARRY_IGNORE_DIRS, PARRY_SCAN_MODE) — the hook command inherits them. Alternatively, pass flags directly in the hook command: parry-guard --hf-token-path ~/.hf-token --ignore-dirs /home/user/trusted hook. See Config for all options.

Project scanning

By default, parry auto-monitors every new project — scanning is active from the first session with no prompt. To opt out of a specific repo, run parry-guard ignore <path>.

To restore the old ask-first behavior, set PARRY_ASK_ON_NEW_PROJECT=true (or askOnNewProject = true in Nix). See docs/opt-in-flow.md for the full flow.

Command Description
parry-guard monitor [path] Enable scanning for a repo
parry-guard ignore [path] Disable scanning for a repo
parry-guard reset [path] Clear state and caches, back to unknown
parry-guard status [path] Show current repo state and findings
parry-guard repos List all known repos and their states

All commands default to the current directory if path is omitted.

What each hook does

  • PreToolUse: 7-layer security — ignored/unknown repo skip, taint enforcement, CLAUDE.md scanning, exfil blocking, destructive operation detection, sensitive path blocking, input content injection scanning (Write/Edit/Bash/MCP tools)
  • PostToolUse: Scans tool output for injection/secrets, auto-taints project on detection
  • UserPromptSubmit: Audits .claude/ directory for dangerous permissions, injected commands, hook scripts

Daemon & Cache

The daemon keeps ML models in memory and can be run standalone with parry-guard serve --idle-timeout 1800. Hook calls auto-start it if not running.

Scan results are cached in ~/.parry-guard/scan-cache.redb (30-day TTL, ~8ms cache hits vs ~70ms+ inference). Cache is shared across projects and pruned hourly.

Detection Layers

Multi-stage, fail-closed (if unsure, treat as unsafe):

  1. Unicode — invisible characters (PUA, unassigned codepoints), homoglyphs, RTL overrides
  2. Substring — Aho-Corasick matching for known injection phrases
  3. Secrets — 40+ regex patterns for credentials (AWS, GitHub/GitLab, cloud providers, database URIs, private keys, etc.)
  4. ML Classification — DeBERTa v3 transformer with text chunking (256 chars, 25 overlap) and head+tail strategy for long texts. Configurable threshold (default 0.7).
  5. Bash Exfiltration — tree-sitter AST analysis for data exfil: network sinks, command substitution, obfuscation (base64, hex, ROT13), DNS tunneling, cloud storage, 60+ sensitive paths, 40+ exfil domains
  6. Script Exfiltration — same source→sink analysis for script files across 16 languages

Scan modes

Mode Models Latency/chunk Backend
fast (default) DeBERTa v3 ~50-70ms any
full DeBERTa v3 + Llama Prompt Guard 2 ~1.5s candle only
custom User-defined (~/.config/parry-guard/models.toml) varies any

Use fast for interactive workflows; full for high-security or batch scanning (parry-guard diff --full). The two models cover different blind spots — DeBERTa v3 catches common injection patterns while Llama Prompt Guard 2 is better at subtle, context-dependent attacks (role-play jailbreaks, indirect injections). Running both as an OR ensemble reduces missed attacks at ~20x higher latency per chunk.

Note: full mode requires the candle backend — Llama Prompt Guard 2 does not ship an ONNX export. Build with --features candle --no-default-features to use full mode.

Config

Global flags

Flag Env Default Description
--threshold PARRY_THRESHOLD 0.7 ML detection threshold (0.0–1.0)
--claude-md-threshold PARRY_CLAUDE_MD_THRESHOLD 0.9 ML threshold for CLAUDE.md scanning (0.0–1.0)
--scan-mode PARRY_SCAN_MODE fast ML scan mode: fast, full, custom
--hf-token HF_TOKEN HuggingFace token (direct value)
--hf-token-path HF_TOKEN_PATH /run/secrets/hf-token-scan-injection HuggingFace token file
--ask-on-new-project PARRY_ASK_ON_NEW_PROJECT false Ask before monitoring new projects (default: auto-monitor)
--ignore-dirs PARRY_IGNORE_DIRS Parent directories to ignore — all repos under these paths are skipped (comma-separated)

Subcommand flags

Flag Env Default Description
serve --idle-timeout PARRY_IDLE_TIMEOUT 1800 Daemon idle timeout in seconds
diff --full false Use ML scan instead of fast-only
diff -e, --extensions Filter by file extension (comma-separated)

Env-only

Env Default Description
PARRY_LOG warn Tracing filter (trace, debug, info, warn, error)
PARRY_LOG_FILE ~/.parry-guard/parry-guard.log Override log file path

Custom patterns: ~/.config/parry-guard/patterns.toml (add/remove sensitive paths, exfil domains, secret patterns). Custom models: ~/.config/parry-guard/models.toml (used with --scan-mode custom, see examples/models.toml).

ML Backends

One backend is always required (enforced at compile time). Nix default is ONNX (x86_64-linux, aarch64-linux, aarch64-darwin). Use candle package on other platforms.

Feature Description
onnx-fetch ONNX, statically linked (downloads ORT at build time). Default.
candle Pure Rust ML. Portable, no native deps. ~5-6x slower.
onnx ONNX, you provide ORT_DYLIB_PATH.
onnx-coreml (experimental) ONNX with CoreML on Apple Silicon.
# Build with Candle instead of ONNX
cargo build --no-default-features --features candle

Performance

Apple Silicon, release build, fast mode (DeBERTa v3 only). Candle is 5-6x slower than ONNX (default). Run just bench-candle / just bench-onnx to reproduce (requires HF_TOKEN).

Scenario ONNX (default) Candle
Short text (1 chunk) ~10ms ~61ms
Medium text (2 chunks) ~32ms ~160ms
Long text (6 chunks) ~136ms ~683ms
Cold start (daemon + model load) ~580ms ~1s
Fast-scan short-circuit ~7ms ~7ms
Cached result ~8ms ~8ms

Llama Prompt Guard 2 does not ship an ONNX export, so full mode requires the candle backend.

Contributing

See CONTRIBUTING.md for development setup, commands, and contribution guidelines.

Credits

License

MIT

Llama Prompt Guard 2 (used in full scan mode) is licensed separately under the Llama 4 Community License. See LICENSE-LLAMA.

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

parry_guard-0.1.0-py3-none-musllinux_1_2_x86_64.whl (8.8 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

parry_guard-0.1.0-py3-none-musllinux_1_2_aarch64.whl (8.4 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

parry_guard-0.1.0-py3-none-macosx_11_0_arm64.whl (8.2 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

parry_guard-0.1.0-py3-none-macosx_10_12_x86_64.whl (8.3 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file parry_guard-0.1.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for parry_guard-0.1.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 4de712351c7794f2a632a31e9ec4be0515e6542f8af64446625e888ced585a1c
MD5 a76c1fc4f705e39fe5fcc6333702ff5b
BLAKE2b-256 890f37bccedfcd02e65f1bd8ca388395677220449b8158dfa8d5b6780c894bcd

See more details on using hashes here.

Provenance

The following attestation bundles were made for parry_guard-0.1.0-py3-none-musllinux_1_2_x86_64.whl:

Publisher: release.yaml on vaporif/parry-guard

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

File details

Details for the file parry_guard-0.1.0-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for parry_guard-0.1.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 4fbbce3b5cd9fcce3fd253dc8e598294f6cc4171c17988f3bdaa485e8dc8f3e3
MD5 3c7789e0f056ffab8bee49cf28de4452
BLAKE2b-256 0c9447b6aea63bec7ceb3d0f9ef02c4f1be54544483b7bcb4b62522b3ba80956

See more details on using hashes here.

Provenance

The following attestation bundles were made for parry_guard-0.1.0-py3-none-musllinux_1_2_aarch64.whl:

Publisher: release.yaml on vaporif/parry-guard

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

File details

Details for the file parry_guard-0.1.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for parry_guard-0.1.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8a1015601d37fb325cbbfa4212d8c2fbcf0630c620bb9416369edf1ecb70de3b
MD5 43238a2a4aca73fdb942b98f16f02451
BLAKE2b-256 a81c99d7dc2751e734500405ca070ba763f731a1c79a14ecc1062be7c6708d41

See more details on using hashes here.

Provenance

The following attestation bundles were made for parry_guard-0.1.0-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yaml on vaporif/parry-guard

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

File details

Details for the file parry_guard-0.1.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for parry_guard-0.1.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 07a451600a65a7cab6c21ba789405505af21bff1e0d619b9e66a5747fdde20bd
MD5 88cba8ac698876d247b0170b9fa21e71
BLAKE2b-256 75eab211c1458f8b38b3bdea34e30a454fe47f30af93c36d55d8e2e813d866eb

See more details on using hashes here.

Provenance

The following attestation bundles were made for parry_guard-0.1.0-py3-none-macosx_10_12_x86_64.whl:

Publisher: release.yaml on vaporif/parry-guard

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