llm-security/examples/bash-evasion-gallery/expected-findings.md
Kjell Tore Guttormsen 58d2e8ad8d
fix(av-surface): no runnable base64-to-shell line on disk
PLAN § v8.1.3 tillegg a. The bash-evasion gallery's T8 comment held a
complete base64-decode-into-shell line whose 16-char blob decodes to a
home-directory deletion, under probe (b)'s 24-char floor. Probe (b2)
found two more of the same shape, fixed here too: the gallery README's
T8 row and tests/e2e/attack-chain.test.mjs (an /etc deletion). Chosen
over an exception list because the gate should have none.

The gallery and the e2e test now encode the blob at runtime from the
same fragments; the README shows a placeholder. Gallery: 10/10 blocked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 11:35:50 +02:00

2.7 KiB

Expected Findings — Bash Evasion Gallery

This is the testable contract. run-evasion-gallery.mjs exits 0 only when every T-tag produces a BLOCK.

Per-tag contract

Tag Hook stderr must contain
baseline BLOCKED: Destructive command detected — Filesystem root destruction (rm -rf /)
T1 BLOCKED: Destructive command detected — Filesystem root destruction (rm -rf /)
T2 BLOCKED: Destructive command detected — Filesystem root destruction (rm -rf /)
T3 BLOCKED: Destructive command detected — Filesystem root destruction (rm -rf /)
T4 BLOCKED: Destructive command detected — Filesystem root destruction (rm -rf /)
T5 BLOCKED: Destructive command detected — Filesystem root destruction (rm -rf /)
T6 BLOCKED: Destructive command detected — Filesystem root destruction (rm -rf /)
T7 BLOCKED: Destructive command detected — Filesystem root destruction (rm -rf /)
T8 BLOCKED: Destructive command detected — T8 — base64-pipe-shell idiom (echo BLOB | base64 -d | sh)
T9 BLOCKED: Destructive command detected — Filesystem root destruction (rm -rf /)

All cases must exit with code 2.

Why $HOME instead of /

The "Filesystem root destruction" BLOCK_RULE regex requires a word-boundary anchor after the destination path:

\brm\s+(?:-[a-zA-Z]*f[a-zA-Z]*\s+|--force\s+)*-[a-zA-Z]*r[a-zA-Z]*\s+(?:\/|~|\$HOME)\b

rm -rf / ends with / followed by end-of-string; both / and EOL are non-word, so \b does not match. The variants rm -rf /tmp, rm -rf $HOME, and rm -rf /etc all match — the trailing word character provides the boundary.

This gallery uses $HOME because it is unambiguously destructive and the regex fires deterministically. The literal rm -rf / edge case is not part of this contract — it is covered by Claude Code 2.1.98+ harness-level checks.

Side effects

  • No file is modified
  • No real bash is invoked — only node hooks/scripts/...
  • Each hook spawn has tool_input.command set to the disguised variant — bash never sees these strings
  • No mutation of $HOME, /, /tmp, or anywhere else

Notes for forks

  • If bash-normalize.mjs adds new T-tags (T10+), add a new case to CASES and a corresponding row above
  • If a BLOCK_RULE in pre-bash-destructive.mjs is renamed, update the stderr-pattern column above (the assertion lives in expected-findings.md for documentation; the run script only checks exit code 2, so it continues to pass after a rename)
  • The base64 blob in T8 (T8_BLOB) is built at runtime from the same fragments as the baseline command, so changing the canonical destructive target updates it too. No runnable base64-to-shell line is kept on disk (v8.1.3)