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.0a4-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.0a4-py3-none-musllinux_1_2_aarch64.whl (8.4 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

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

Uploaded Python 3macOS 11.0+ ARM64

parry_guard-0.1.0a4-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.0a4-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for parry_guard-0.1.0a4-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 e2d67d03214a3befd8b2b6a268f8d2ffc097981053f2ea38ecf8415b9ea30572
MD5 54d3f1a4dcb715fcb76f4b7102c5dbf1
BLAKE2b-256 2aa0148a6c571ab0c97351c8382fde5ec0dd27122118e3213d3e86cfe770d4cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for parry_guard-0.1.0a4-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.0a4-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for parry_guard-0.1.0a4-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 1acb356699c56ea7a1b9609eee9919ca578f3555f60be03ef006e6f7b1810c6c
MD5 cc124c55e112b18fdbd4edd766fd9d6e
BLAKE2b-256 aa8ae8bce7307b7a90bef26c3b77285144b7a3ca0b9ea4b01359290e9a256e44

See more details on using hashes here.

Provenance

The following attestation bundles were made for parry_guard-0.1.0a4-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.0a4-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for parry_guard-0.1.0a4-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0f086ec49748b5ff09cac13eee50d2adeac1255f0d6e6d7f4e5c9f9709dd7d01
MD5 a4c2c7cbf952b60df6b5a3e6efedf5e9
BLAKE2b-256 75447ea3751bd56495be36b1c0f68b3dbdd3ce8b1a3ae9a7edd39885dc234aaf

See more details on using hashes here.

Provenance

The following attestation bundles were made for parry_guard-0.1.0a4-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.0a4-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for parry_guard-0.1.0a4-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 083d7688901e059becd8df8a10b61aeb8815a6b20537f51aba2e0a3e1764ea21
MD5 74e4ac4e31b750719a0c0ed5a849c777
BLAKE2b-256 b6801e03c728f5460bda8649a6ec8f0eab6e9cbd00b5cebabb8212689cbe6b96

See more details on using hashes here.

Provenance

The following attestation bundles were made for parry_guard-0.1.0a4-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