Skip to main content

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

Project description

Parry Guard Parry-guard

ci audit codecov Mentioned in Awesome Claude Code

Prompt injection scanner for Claude Code hooks. Catches injection attacks, leaked secrets, and data exfiltration in tool inputs and outputs.

Early development - bugs and false positives happen. Tested on Linux and macOS.

Prerequisites

The ML models are gated on HuggingFace, so you need to accept licenses 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 bin

# Candle backend (pure Rust, no native deps, portable)
cargo install --path bin --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

HuggingFace token

Provide your token via 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 starts on the first scan, downloads the model on the first run, and shuts down after 30 minutes idle. Non-Nix users: set env vars in your shell profile or pass flags directly (see Config).

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 get 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 Effect
parry-guard monitor [path] Turn on scanning for a repo
parry-guard ignore [path] Turn off 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

path defaults to the current directory.

What each hook does

PreToolUse runs 7 checks in order, stopping at the first match: ignored/unknown repo skip, taint enforcement, CLAUDE.md scanning, exfil blocking, destructive operation detection, sensitive path blocking, and input content injection scanning (Write/Edit/Bash/MCP tools).

PostToolUse scans tool output for injection and secrets. If it finds something, it auto-taints the project.

UserPromptSubmit audits your .claude/ directory for dangerous permissions, injected commands, and hook scripts.

Daemon and cache

You can run the daemon standalone with parry-guard serve --idle-timeout 1800. Hook calls start it automatically if it isn't running.

Scan results are cached in ~/.parry-guard/scan-cache.redb with a 30-day TTL. Cache hits take about 8ms vs 70ms+ for inference. The cache is shared across projects and pruned hourly.

Detection layers

The scanner is fail-closed: if it can't tell whether something is safe, it treats it 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 a head+tail strategy for long texts. Threshold defaults to 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-to-sink analysis for script files across 16 languages
Scan modes
Mode Models Latency per 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 work and full for high security or batch scanning (parry-guard diff --full). The two models have different blind spots — DeBERTa v3 is good at common injection patterns, while Llama Prompt Guard 2 is better at subtle stuff like role-play jailbreaks and indirect injections. Running both as an OR ensemble means fewer missed attacks, but at roughly 20x higher latency per chunk.

Note: full mode needs the candle backend because Llama Prompt Guard 2 doesn't have an ONNX export. Build with --features candle --no-default-features.

Config

Global flags
Flag Env Default Effect
--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, comma-separated. All repos under these paths get skipped.
Subcommand flags
Flag Env Default Effect
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)
Environment-only variables
Env Default Effect
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 defaults to ONNX on x86_64-linux, aarch64-linux, and aarch64-darwin. Use the candle package on other platforms.

Feature
onnx-fetch ONNX, statically linked (downloads ORT at build time). Default.
candle Pure Rust ML. Portable, no native deps. About 5-6x slower.
onnx ONNX, you provide ORT_DYLIB_PATH.
onnx-coreml (experimental) ONNX with CoreML on Apple Silicon.

Performance

Apple Silicon, release build, fast mode (DeBERTa v3 only). Candle is about 5-6x slower than ONNX. 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

Contributing

See CONTRIBUTING.md.

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.4-py3-none-musllinux_1_2_x86_64.whl (9.0 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

parry_guard-0.1.4-py3-none-musllinux_1_2_aarch64.whl (8.6 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

parry_guard-0.1.4-py3-none-macosx_14_0_x86_64.whl (8.4 MB view details)

Uploaded Python 3macOS 14.0+ x86-64

parry_guard-0.1.4-py3-none-macosx_14_0_arm64.whl (8.3 MB view details)

Uploaded Python 3macOS 14.0+ ARM64

File details

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

File metadata

File hashes

Hashes for parry_guard-0.1.4-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 7a04535a28aca3e8d26839bfeabf1ad233ecace8c8da791c54513066644e6005
MD5 75c3d564ec9f36d13d461547974987eb
BLAKE2b-256 a586d619e4de66b408baf52f01623264b531884fbaae93f16a547780b52ef586

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for parry_guard-0.1.4-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 0838086b79f5bcb1866ef24340fc15bb730917b671cbf5b7a5cda33e2fce9329
MD5 4fa65bec78f5392b79ad05eb991c8862
BLAKE2b-256 d5b6a1e69a013ff574a86594d77478b68b50f8aea03174e195f285e45c94a2b7

See more details on using hashes here.

Provenance

The following attestation bundles were made for parry_guard-0.1.4-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.4-py3-none-macosx_14_0_x86_64.whl.

File metadata

File hashes

Hashes for parry_guard-0.1.4-py3-none-macosx_14_0_x86_64.whl
Algorithm Hash digest
SHA256 786340662d6c65bfa43a2a557dfe4f4eb376b64a4b75a2f9f99d22688bca234d
MD5 c7a7e7385cda17466bda7bb102c087a0
BLAKE2b-256 8e965e24c525c282f7c437741c276e4d0e2dbe77366497e0b6ad7e7838cfaf9b

See more details on using hashes here.

Provenance

The following attestation bundles were made for parry_guard-0.1.4-py3-none-macosx_14_0_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.4-py3-none-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for parry_guard-0.1.4-py3-none-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 927715d91b1aae6f16cec5f4cc4371c3a657654e4c459ae8113f299bad51fdb1
MD5 4d40d8799f152a00d96b6fdf966bfbdf
BLAKE2b-256 8341ddfc582c0cf59eb32e357190018282f667a797e2f432a07765e0fccf8773

See more details on using hashes here.

Provenance

The following attestation bundles were made for parry_guard-0.1.4-py3-none-macosx_14_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.

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