Security Policy¶
Reporting a vulnerability¶
Please do not open a public GitHub issue for a suspected security vulnerability. Instead, email bonadioar@gmail.com with:
- A description of the vulnerability and its potential impact.
- Steps to reproduce (a minimal policy/tool-call snippet is usually enough).
- The version of
chokepointaffected (python -c "import chokepoint; print(chokepoint.__version__)").
We aim to acknowledge reports within a few business days.
Trust boundaries to be aware of¶
Chokepoint is an authorization layer, not a sandbox. A few things worth being explicit about:
- The CLI executes arbitrary code.
chokepoint report,chokepoint lint,chokepoint replay --agent <file>, andchokepoint repl --agent <file>all load the target file as a Python module viaimportlib.utiland execute it (exec_module) to read its module-levelPOLICIES/REGISTRY. This is inherent to how the CLI discovers policies — only ever point it at files you trust, the same way you wouldn't runpython untrusted_file.py. - Policy predicates run with the same privileges as your agent process.
pre/postlambdas,active_when, andapplies_toare plain Python callables evaluated in-process — they are not sandboxed. Chokepoint protects against bugs in predicates (a raising predicate fails closed toBLOCKrather than crashing the call — seeCLAUDE.md), not against malicious predicate code. - The default
EscalationHandlerdenies by design. With no handler registered for anescalate_toscheme, escalations are logged and denied (fail-safe) rather than silently approved. Three real handlers ship underchokepoint.escalation: SlackEscalationHandlerrequires a non-emptyapproversset (Slack user IDs) at construction — without it, anyone in the channel reacting with the approve emoji would approve the action. Keep your bot token out of source control (an env var, a secrets manager — not a literal in code).WebhookEscalationHandlertrusts whateverurlyou configure and whatever JSON body it returns — put your own authentication inheaders(a shared secret, a bearer token) and only ever point it at an endpoint you control.CLIEscalationHandleris local-only (stdin), no network exposure, but only meaningful when someone is actually watching the terminal. If you implement your ownEscalationHandlerinstead, the same rule applies: make sure it authenticates its approval source — Chokepoint has no opinion on how you verify "a human approved this."- Tool arguments are redacted before they are recorded, but redaction is
best-effort. Values matching a known credential shape, and values under
names like
password/api_key/authorization, are replaced before they reach the ledger, the JSONL sink, the compliance exports or an escalation message (seechokepoint.redaction). PII patterns are opt-in viaconfigure_redaction(include_pii=True). This is pattern matching, not classification: a credential in a shape Chokepoint doesn't recognise, or an identifier under a name it doesn't know, is recorded verbatim. Add your own withkeys=/extra_patterns=, or plug in a real DLP scrubber viaconfigure_redaction(redactor=...). ActionLedger's JSONL sink (sink_path) is plain-text and unencrypted. Redaction reduces what ends up there; it does not make the file safe to leave world-readable. Store it somewhere access-controlled, and treat it as sensitive regardless — tool names, caller identities, session ids and argument structure are all still present.- Policies see unredacted arguments, by design. A predicate written to check a credential has to be able to see one. Redaction applies to what is written, not to what is evaluated — so a malicious or buggy predicate can still observe (and, if it does I/O, exfiltrate) raw argument values. This is the same trust boundary as "predicates are unsandboxed", above.
Supported versions¶
Pre-1.0.0, only the latest released version receives fixes.