HEEL is a security tool, so its own security model matters. This document is the threat model, the production-hardening checklist, and the responsible-disclosure policy.
Please report security issues privately via a GitHub security advisory on ancilis/heel, or by
email to the maintainers, not a public issue. We aim to acknowledge within 3 business days. Do
not include real exploit payloads against third-party systems; HEEL is synthetic-first by design.
HEEL rehearses how a customer or third party could abuse a product you own, before launch. It is a pre-launch abuse-simulation harness, not a replacement for application-security review, penetration testing, or a bug-bounty program. Findings are predicted, contained, canary-only proofs that an abuse path is reachable, they are leads to harden, not exploit code.
HEEL is agent-native: its canonical surface is an MCP server that other agents call, and a calling agent is an untrusted, possibly prompt-injected channel. HEEL therefore treats the caller as a confused deputy:
- Scopes are human-only and out-of-band. A scope (target allowlist + limits + approver + expiry)
is created only via
heel scope create --confirmand written as an HMAC-signed file. No MCP / REST / agent code path can create, widen, add a target to, relax the limits of, or escape a scope: those tools do not exist in the registry, by construction. - Immutable from the caller side. The server only loads + verifies scopes; it never writes them. Hand-editing a signed scope file breaks the signature and the scope fails closed.
- Every escalation is rejected and logged. Out-of-allowlist targets, forged scope ids,
prompt-injected target strings, injected
allowlist/limit-override arguments, and forged scope-mutation tool calls are all rejected at the boundary and written to the containment log. - Tamper-evident self-audit. Every run is recorded in an append-only, HMAC-hash-chained
containment log attributed to the caller;
verify_chaindetects mutation, truncation, or deletion.
Synthetic-first · detection-not-weaponization (contained, canary-only PoCs, no real exfiltration or resource exhaustion) · never generates prohibited or illegal content under any framing (guardrail presence is verified with benign canaries only) · no real-PII harvesting · containment/back-off · plausibility-weighting · severity honesty · immutable self-audit · lane discipline (a genuine software vulnerability is handed off to AppSec; a pure model-jailbreak surface is handed off to model red-team: neither is weaponized or counted as a product-abuse finding).
- Separate key from data. Set
HEEL_SIGNING_KEYto a path (or secret mount) outsideHEEL_HOME. Co-locating the key with the data dir only deters actors without filesystem access.heel doctorwarns when the key is co-located. - Restrict the data dir.
HEEL_HOME(default./.heel) holds signed scopes, the SQLite store, and the containment log. Lock it down (chmod 700); it is git-ignored by default. - The REST API has no transport auth of its own.
heel-restbinds to127.0.0.1and relies on the scope-authorization model for capability control, not network access control. Do not expose it publicly; front it with your own authenticated gateway / mTLS / network policy if it must be reachable beyond localhost. It cannot mint or widen a scope regardless. Read routes (/runs/{id}/...) are not confidential between local callers: all callers on the loopback interface share one trust domain in v1; theX-Heel-Callerheader is self-asserted attribution, not authentication. The server also rejects non-loopbackHostheaders (anti DNS-rebinding) and any request carrying anOrigin(anti-CSRF). - Run against synthetic or explicitly-authorized targets only. v1 ships two synthetic targets; real-target adapters are out of v1 scope. A human must authorize any target out-of-band before it can be run.
- LLM control loop. The optional
HEEL_MODEL=anthropicpath sends only observable affordance properties (never secrets/PII) to the Messages API and only receives declarative scenario proposals; it stays in HEEL's lane and falls back to the offline deterministic model on any error. Review your data-egress policy before enabling it.
v1.x receives security fixes. The pure-stdlib core has zero runtime dependencies, minimizing supply-chain surface.