Input & Output Controls
Code Sanitizer
code-sanitizer blocks text that contains dangerous commands, such as rm -rf, DROP TABLE, or a request to the cloud metadata address. It checks all message text, not only code blocks, and you can add your own patterns.
Set block_on_match: true if a match must not go through. The default result, redact, records a cleaned copy in the decision details but does not change the actual traffic.
Configuration
pack:
name: code-sanitizer-example
version: 1.0.0
enabled: true
policies:
chain:
- code-sanitizer
policy:
code-sanitizer:
enabled: true
block_on_match: true
additional_patterns:
- AKIA[0-9A-Z]{16}To check the model response instead of the request, set the stage on the chain entry:
policies:
chain:
- code-sanitizer:
stage: pre-responseVerify a match and usual code
Add these tests to the first file. The first input is text for the test. Do not run it as a command.
testing:
suites:
- name: code-sanitizer
cases:
- name: blocks-chmod-777
input: {messages: [{role: user, content: "chmod 777 example.txt"}]}
expected: {verdict: block, reason_code: code-sanitizer.flagged}
- name: allows-print
input: {messages: [{role: user, content: "print(\"Hello\")"}]}
expected: {verdict: allow, reason_code: ok}Run verdictan policy test --json. Both cases pass. A question about chmod 777 also matches, because the control cannot tell intent.
Fields
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | false turns off every check. The control then always allows with code-sanitizer.ok. |
block_on_match | boolean | false | true blocks on a match. false returns redact. |
additional_patterns | list of strings | [] | Regular expressions checked after the built-in set. A pattern that does not compile is skipped. |
Built-in patterns
Case does not matter. \s+ matches one or more spaces.
| Pattern | Matches |
|---|---|
rm\s+-rf | Recursive forced deletion |
drop\s+table | SQL table deletion |
169\.254\.169\.254 | Cloud instance metadata address |
curl\s+https?://localhost | HTTP request to the local host |
chmod\s+777 | World-writable file permission |
aws\s+s3\s+cp.+--recursive | Recursive S3 copy |
How it works
- The gateway joins the message text of the active stage: the request messages in
pre-request, or the response text inpre-response. - The control runs the built-in patterns, then
additional_patterns. - Each match becomes a finding, and the matched text is replaced with
[redacted code pattern]in a copy. - No findings:
allowwithcode-sanitizer.ok. - Findings with
block_on_match: true:blockwithcode-sanitizer.flagged. - Findings with
block_on_match: false:redactwithcode-sanitizer.flagged.
The details contain flagged, sanitized_text, and findings.
Phase and verdicts
| Item | Value |
|---|---|
| Stages | pre-request (default), pre-response |
| Request families | Chat Completions, Completions, Responses, Messages |
| Verdicts | allow, redact, block |
| Reason codes | code-sanitizer.ok, code-sanitizer.flagged |
Limits and failure behavior
- A block returns HTTP
400with error codecontent_policy_violation. Inpre-request, the provider never gets the request. Inpre-response, the client never gets the model text. redactdoes not remove the code. Inpre-request, it starts the shared PII redactor, which has no code patterns. Inpre-response, the text passes unchanged. Useblock_on_match: truewhen a match must stop.- All message text is checked, not only fenced code.
- Six built-in patterns are not a vulnerability scanner.
- An
additional_patternsentry that does not compile is silently skipped. Test each one withverdictan policy test. - Lint rejects unknown fields. A block with a wrong type that bypasses lint runs with all defaults.
Next steps
- Conditional Chain Configuration:
stageandwhenon a chain entry. - Agent Firewall: control the tool calls that run code.
- Document Analyzer: the same checks on documents in the request.