10 releases

new 0.1.0-alpha.10 Mar 10, 2026
0.1.0-alpha.9 Mar 5, 2026
0.1.0-alpha.3 Feb 27, 2026

#342 in Development tools


Used in 3 crates (2 directly)

MIT license

84KB
1.5K SLoC

Parry

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

Install

cargo-binstall

cargo binstall parry-ai

From source

# Default (Candle backend - pure Rust, no native deps)
cargo install --path crates/cli

# ONNX backend (faster inference, needs native libs)
cargo install --path crates/cli --no-default-features --features onnx-fetch

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 = {
    enable = true;
    package = inputs.parry.packages.${pkgs.system}.default;  # candle (default)
    # package = inputs.parry.packages.${pkgs.system}.onnx;  # onnx backend (5-7x faster, see Performance)
    hfTokenFile = config.sops.secrets.hf-token.path;
    ignorePaths = [ "/home/user/repos/parry" ];

    # 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; }
    # ];
  };
}

You still need to configure the Claude Code hook separately (see below).

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

2. Add Claude Code hook

Add to ~/.claude/settings.json:

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

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_PATHS, PARRY_SCAN_MODE) — the hook command inherits them. Alternatively, pass flags directly in the hook command: parry --hf-token-path ~/.hf-token --ignore-path /home/user/safe hook. See Config for all options.

What each hook does

  • PreToolUse: 5-layer security — taint enforcement, CLAUDE.md scanning, exfil blocking, 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 serve --idle-timeout 1800. Hook calls auto-start it if not running.

Scan results are cached in ~/.parry/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
fast (default) DeBERTa v3 ~50-70ms
full DeBERTa v3 + Llama Prompt Guard 2 ~1.5s
custom User-defined (~/.config/parry/models.toml) varies

Use fast for interactive workflows; full for high-security or batch scanning (parry 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.

Config

Global flags

Flag Env Default Description
--threshold PARRY_THRESHOLD 0.7 ML detection threshold (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
--ignore-path PARRY_IGNORE_PATHS Paths to skip scanning (comma-separated / repeatable)

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/parry.log Override log file path

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

ML Backends

One backend is always required (enforced at compile time). Nix builds candle by default.

Feature Description
candle Pure Rust ML. Portable. Default.
onnx-fetch ONNX with auto-download. Works pretty much everywhere.
onnx ONNX, you provide ORT_DYLIB_PATH.
onnx-coreml (experimental) ONNX with CoreML on Apple Silicon.
# Build with ONNX instead of candle
cargo build --no-default-features --features onnx-fetch

Performance

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

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

Llama Prompt Guard 2 (~1.5s/chunk) does not ship an ONNX export, so full mode uses Candle for PG2 regardless of backend.

Development

nix develop              # enter dev shell with all tools (rust, just, taplo, typos, actionlint)

just check               # run all checks (clippy, test, fmt, lint, typos, audit)
just build               # build workspace (candle)
just build-onnx          # build workspace (onnx-fetch)
just test                # run tests
just e2e            # run ML e2e tests (requires HF_TOKEN, see below)
just bench-candle        # benchmark ML inference, candle backend (requires HF_TOKEN)
just bench-onnx          # benchmark ML inference, ONNX backend (requires HF_TOKEN)
just clippy              # lint
just fmt                 # format all (rust + toml)
just setup-hooks         # configure git hooks

ML end-to-end tests

The ML e2e tests are #[ignore]d by default since they require a HuggingFace token and model downloads. To run them:

HF_TOKEN=hf_... just e2e

This tests both fast (DeBERTa only) and full (DeBERTa + Llama PG2) modes with semantic injection prompts and clean text. First run downloads models (~100MB each).

Credits

License

MIT

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

Dependencies

~35–56MB
~1M SLoC