test(fuzz): coverage-guided fuzzing for untrusted-input surfaces#37
Open
seonghobae wants to merge 4 commits into
Open
test(fuzz): coverage-guided fuzzing for untrusted-input surfaces#37seonghobae wants to merge 4 commits into
seonghobae wants to merge 4 commits into
Conversation
Add cargo-fuzz (libFuzzer) harnesses plus a stable proptest mirror for the gateway's attacker-controlled and untrusted-config surfaces, identified with CodeGraph as the reachable, untested entry points for arbitrary input: - fuzz_score_request -> waf_ids_core::score_request (request scorer: percent-decode + signature/threat/DNSBL/anomaly matching) - fuzz_appdata_json -> serde_json::from_str::<AppData> (persisted state file) - fuzz_parse_admin_tokens -> waf_ids_ai_soc::parse_admin_tokens (ADMIN_TOKENS config) - fuzz_dnsbl_zone -> export_dnsbl_zone / validate_dnsbl (zone-file escaping) Each target asserts no panic on arbitrary input plus surface-specific invariants (non-empty reason, deterministic scoring, serde round-trip, no empty token/actor, fully-escaped TXT payloads), and ships a seed corpus of real attack payloads and edge cases. The fuzz crate is an isolated workspace so `cargo test --workspace` at the root is unaffected. crates/waf-ids-core/tests/fuzz_invariants.rs and tests/fuzz_invariants.rs re-assert the same invariants via proptest on stable, so they stay green in primary CI without a nightly toolchain. CI: .github/workflows/fuzz.yml runs each target for a bounded budget (60s/target on PRs, 300s nightly) to keep cost predictable. All added deps are permissive (cargo-fuzz, libfuzzer-sys, arbitrary, proptest: MIT OR Apache-2.0). Docs in docs/fuzzing.md; fuzzing survey paper in docs/papers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RTAMs4bpSZS77Xe3RQjv9P
Fixes the fuzz_dnsbl_zone crash and restores the coverage-evidence gate to 100% line/function coverage for PR #37. Real bug (fuzz crash): export_dnsbl_zone rendered the untrusted `origin` and each entry `code` into the zone file verbatim. A newline plus double quotes in `origin` (or a non-IP `code`) broke out of the generated zone and produced TXT records with unescaped quotes, violating the fuzz invariant. - Sanitize the zone origin to DNS-safe characters (LDH, `_`, `.`); empty input falls back to the reserved `.invalid` TLD. - Require each DNSBL response `code` to parse as an IP literal, re-rendering the canonical form and skipping entries that do not. - Escape control characters (including raw newlines) in TXT payloads as BIND decimal escapes so a crafted reason/source cannot inject extra zone lines. - Add regression tests reproducing the crash shape and the escaping paths. Coverage-evidence (workspace 100% line/function gate): move the env-parsing helpers into the tested library, add `run_from_env` (bound + served via an ephemeral listener under an immediate shutdown in-process), reduce main.rs to a thin shim covered end-to-end by tests/binary.rs (graceful SIGTERM shutdown), and add unit tests for every configuration branch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RTAMs4bpSZS77Xe3RQjv9P
…case Adds the exact libFuzzer crash input (newline + quotes in `origin`) to the fuzz_dnsbl_zone corpus so CI replays it and proves the zone-injection fix holds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RTAMs4bpSZS77Xe3RQjv9P
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds coverage-guided fuzzing (cargo-fuzz / libFuzzer) plus a stable proptest mirror for the gateway's attacker-controlled and untrusted-config surfaces. Targets were selected with CodeGraph (
codegraph explore), which surfaced the request scorer, the persisted-state deserializer, the admin-token config parser, and the DNSBL zone generator as the reachable, no-covering-test entry points for arbitrary input.Fuzz targets (
fuzz/)fuzz_score_requestwaf_ids_core::score_requestreasonnon-empty; deterministic scoringfuzz_appdata_jsonserde_json::from_str::<AppData>(state file)fuzz_parse_admin_tokenswaf_ids_ai_soc::parse_admin_tokens(ADMIN_TOKENS)fuzz_dnsbl_zoneexport_dnsbl_zone/validate_dnsblEach target ships a seed corpus of real attack payloads (SQLi, XSS, traversal, cmd-injection, SSRF, JNDI, percent-encoded) and malformed/edge-case inputs.
Keeping primary CI green
fuzz/crate is an isolated cargo workspace, socargo test --workspaceat the repo root never builds it (no nightly needed for normal CI).crates/waf-ids-core/tests/fuzz_invariants.rsandtests/fuzz_invariants.rsre-assert the same invariants via proptest on stable, so they run in the existing test job.cargo fmt --check,cargo test --locked --workspace, andcargo clippy --locked --workspace --all-targets -- -D warningsall pass.CI job
.github/workflows/fuzz.ymlruns each target on a bounded budget — 60s/target on PRs, 300s/target nightly (cron) + manual dispatch — uploading crash artifacts on failure, so fuzzing cost stays predictable.Licensing
All added dependencies are permissive (MIT OR Apache-2.0): cargo-fuzz, libfuzzer-sys, arbitrary, proptest. No GPL/AGPL. No runtime secrets. Fuzzing survey paper added under
docs/papers/; usage indocs/fuzzing.md.🤖 Generated with Claude Code
https://claude.ai/code/session_01RTAMs4bpSZS77Xe3RQjv9P