Skip to content

False positives: heredoc bodies scanned as executable commands, and the regex secret engine lacks betterleaks' documentation-credential allowlist #230

Description

@JJB1

Two false positives in the local PreToolUse agent gate on CLI 0.10.0. Both share a shape: writing about a dangerous thing is treated as doing it, so security documentation, runbooks, and test fixtures become unwritable.

Related in spirit to the rule-narrowing work in #182 / #205 / #210, but a different subsystem — this is the local command/secret gate, not the remote SAST rules.

Environment: macOS 15 (darwin/arm64) · Node v26.0.0 · @rafter-security/cli 0.10.0 · betterleaks 1.1.2 · Claude Code integration.


1. Heredoc bodies are scanned as if they were executable

Quoted strings and grep arguments are handled correctly. Heredoc bodies are not:

tool_input.command decision
echo "never run rm -rf / on prod" allow ✅
grep -r "rm -rf /" /var/log allow ✅
cat > a.md <<EOFnever run rm -rf / on prodEOF deny
cat > c.md <<EOF … fenced `rm -rf / --no-preserve-root`EOF deny

Reproduce:

printf '%s' '{"tool_name":"Bash","tool_input":{"command":"cat > /tmp/a.md <<EOF\nnever run rm -rf / on prod\nEOF"}}' \
  | rafter hook pretool

Returns "permissionDecision":"deny" for a command whose only effect is writing a markdown file.

Impact: an agent cannot author an incident report, a runbook, a detection rule, or a test fixture that mentions a destructive command. I hit this writing up an unrelated bug report — cat > report.md <<'MD' was denied because the document quoted rm -rf / inside a fenced code block.

Suggested fix: exclude heredoc bodies from pattern matching, the same way quoted strings already are.

2. The regex secret engine lacks betterleaks' allowlist for documentation credentials

The bundled betterleaks correctly allowlists AWS's canonical documentation access key. Rafter's own regex engine does not — and that engine is the one wired into the blocking path:

$ printf 'key = AKIAIOSFODNN7EX*MPLE\n' | betterleaks stdin
INF no leaks found
Write tool, content "betterleaks allowlists AKIAIOSFODNN7EX*MPLE ..."   -> deny
Write tool, same content with one character masked                       -> allow

(Substitute the real AWS documentation key for the * to reproduce. It is masked here because spelling it correctly makes this very issue body unwritable through an agent with the gate enabled — which is the bug.)

Impact: the two engines disagree, and the more naive one holds the veto. Security documentation, onboarding material, test fixtures, and bug reports citing well-known placeholder credentials cannot be written.

Suggested fix: share betterleaks' allowlist of known documentation/test credentials with the regex engine, and reserve the blocking path for matches in executable position.


Happy to test a patch on either.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions