Skip to content

fix(fuzz): drop arithmetic_fuzz inputs that contain banned debug shapes#1622

Merged
chaliy merged 1 commit into
mainfrom
claude/fuzz-arithmetic-input-filter
May 10, 2026
Merged

fix(fuzz): drop arithmetic_fuzz inputs that contain banned debug shapes#1622
chaliy merged 1 commit into
mainfrom
claude/fuzz-arithmetic-input-filter

Conversation

@chaliy
Copy link
Copy Markdown
Contributor

@chaliy chaliy commented May 10, 2026

Summary

The nightly fuzz job on main is red. arithmetic_fuzz inlines fuzz input directly into echo \$(({input})). With unbalanced parens the arithmetic expansion closes early and the remainder is parsed as commands; bash then echoes the unknown command verbatim (bash: /.rustup/toolchains/gww: No such file or directory). That is real-shell stderr, not a TM-INF-022 leak.

Last run: input bytes contained /.rustup/toolchains/ literally and the fuzz harness's leak detector tripped on the banned host-path shape — but no internal Debug formatter ran.

Fix: at the fuzz-input layer, drop inputs that already contain any UNIVERSAL_BANNED substring. Mirrors #1621 for glob_fuzz.

Test plan

  • cargo check on the fuzz crate compiles cleanly
  • Manually dispatch Fuzz Testing on this branch and confirm arithmetic_fuzz job is green

The nightly fuzz job on main is red. `arithmetic_fuzz` inlines fuzz input
directly into `echo $(({input}))`. With unbalanced parens the arithmetic
expansion closes early and the remainder is parsed as commands; bash then
echoes the unknown command verbatim ("bash: /.rustup/toolchains/gww: No
such file or directory"). That is real-shell stderr, not a TM-INF-022
leak.

Last run: input bytes contained `/.rustup/toolchains/` literally and the
fuzz harness's leak detector tripped on the banned host-path shape.

Fix: at the fuzz-input layer, drop inputs that already contain any
`UNIVERSAL_BANNED` substring. This keeps TM-INF-022 detection strict on
real builtin internals while removing the false-positive class. Mirrors
the same fix applied to `glob_fuzz` in #1621.
@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
bashkit 1fad283 Commit Preview URL

Branch Preview URL
May 10 2026, 09:07 AM

@chaliy chaliy merged commit 8513f9d into main May 10, 2026
27 of 28 checks passed
@chaliy chaliy deleted the claude/fuzz-arithmetic-input-filter branch May 10, 2026 09:38
chaliy added a commit that referenced this pull request May 10, 2026
…pe check (#1623)

## Summary

When a fuzz/proptest target inlines arbitrary input bytes into a shell
script, bash and ls produce error messages that quote the input
verbatim:

```
bash: <cmd>: command not found
bash: <path>: No such file or directory
ls:   cannot access '<path>': No such file or directory
```

These echoes can accidentally form a banned substring even when no
internal Debug formatter ran. Two real cases:

- arithmetic_fuzz / glob_fuzz: input contained `/.rustup/toolchains/`
literally; bash echoed it back. Filtered at the input layer in #1621 and
#1622.
- **glob_fuzz (new, dispatched run on this branch):** input ended with
`Tok"`. Bash treated `Tok:` as a command and rendered `bash: Tok::
command not found` — the trailing `:` chrome from bash's error format
glued onto the input's final `:` to form the banned parser-token shape
`Tok::`. Pre-filtering the input for `Tok::` doesn't catch this — the
substring only forms after bash's formatter runs.

## Fix

Structural fix in `assert_fuzz_invariants`: strip lines that match a
recognized real-shell error template before running the banned-shape
check.

- Byte-length cap (`MAX_STDERR_BYTES`) still runs on the **unfiltered**
stderr — flood regressions still caught.
- Host-canary check (TM-INF-013) still runs on the unfiltered stderr —
env-leak regressions still caught.
- The strict `assert_no_leak` path (used by per-builtin tests) is
unchanged — non-fuzz tests must not produce shell echoes in the first
place.

Recognized templates are conservative: prefix `bash: ` or `ls: ` plus a
known suffix. Lines that look similar but don't match the exact template
stay in stderr, so real Debug leaks that happen to coexist with shell
errors still trip the assertion.

## Test plan

- [x] 8 unit tests in `testing::tests` cover both directions — strip
known shell echoes, keep internal panic/Debug lines, keep partial
matches and lines from other tools.
- [x] `cargo test -p bashkit --lib testing::` green
- [x] `cargo test -p bashkit --test proptest_security --all-features`
green (18 cases)
- [x] `cargo clippy -p bashkit --lib --tests -- -D warnings` clean
- [x] `cargo fmt --check` clean
- [x] Threat-model TM-INF-022 section updated to document the carve-out
- [ ] Manually dispatch `Fuzz Testing` on this branch and confirm
`glob_fuzz` job is green
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant