Add Jazzer coverage-guided fuzzing for untrusted-input parsers#118
Open
seonghobae wants to merge 2 commits into
Open
Add Jazzer coverage-guided fuzzing for untrusted-input parsers#118seonghobae wants to merge 2 commits into
seonghobae wants to merge 2 commits into
Conversation
Adds Jazzer (Apache-2.0) JUnit 5 fuzz harnesses for the highest-value untrusted-input surfaces, selected with CodeGraph: - ArtifactTokenParserFuzzTest: fuzzes ArtifactLinkService.verifyReadToken (attacker-controlled HMAC token; forges valid signatures to reach the Base64URL-decode/UUID/epoch-parse path). Invariant: only ArtifactTokenException. - DocumentValidationFuzzTest: fuzzes DefaultDocumentValidationService (filename/extension + policy-override headers). Invariant: only IllegalArgumentException. - TenantClaimsFuzzTest: fuzzes TenantContext.fromHeaders + TenantAccessService.require (tenant/subject/permission + signed-claims timestamp/signature). Invariant: fromHeaders never throws; require only throws ResponseStatusException. Fuzzing immediately surfaced an unhandled java.time.DateTimeException in the token parser: Instant.ofEpochSecond(Long.parseLong(...)) escaped the catch (IllegalArgumentException) block on an out-of-range epoch second, turning a 401 into a 500. Fixed by also catching DateTimeException in ArtifactLinkService.parseAndVerify; the triggering input is committed as a regression seed. Seed corpora, a bounded CI fuzz job (.github/workflows/fuzz.yml: 60s/target on PRs, 10min/target nightly), docs/fuzzing.md, and a foundational coverage-guided fuzzing paper (docs/papers) are included. Regression replay of the seed corpus runs as part of the normal `mvn test` build (348 tests green). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RTAMs4bpSZS77Xe3RQjv9P
|
|
||
| permissions: | ||
| contents: read | ||
| security-events: write |
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 Jazzer (Apache-2.0) coverage-guided fuzzing, integrated with JUnit 5, for the viewer's highest-value untrusted-input surfaces. Targets were chosen using CodeGraph to find the boundaries where attacker-controlled bytes are parsed.
Each harness asserts that arbitrary input only ever yields the documented failure mode, never an unhandled runtime exception.
ArtifactTokenParserFuzzTestArtifactLinkService.verifyReadToken— splits + HMAC-verifies + Base64URL-decodes + parses 10 token fields (UUID, epochInstants). Forges valid signatures to reach the deep parse path.ArtifactTokenException(4xx) escapesDocumentValidationFuzzTestDefaultDocumentValidationService.validateOrThrow— filename/extension + policy-override headersIllegalArgumentExceptionescapesTenantClaimsFuzzTestTenantContext.fromHeaders+TenantAccessService.require— tenant/subject/permission + signed-claims timestamp/signaturefromHeadersnever throws;requireonly throwsResponseStatusExceptionBug found and fixed
Fuzzing immediately surfaced an unhandled
java.time.DateTimeExceptionin the artifact-token parser.Instant.ofEpochSecond(Long.parseLong(...))throwsDateTimeException(which is not anIllegalArgumentException) on an out-of-range but syntactically valid epoch second, escaping thecatch (IllegalArgumentException)block inArtifactLinkService.parseAndVerifyand turning a would-be 401 into a 500. Fixed by also catchingDateTimeException; the triggering input is committed as a regression seed (regression-datetime-epoch-overflow).How it runs
mvn test(default):@FuzzTestmethods run in regression mode, replaying the committed seed corpus as fast unit tests — no libFuzzer driver, cross-platform. 348 tests green (was 336).JAZZER_FUZZ=1 mvn test -Dtest=<Harness>: libFuzzer drives each target for its bounded@FuzzTest(maxDuration = "60s")budget.CI
.github/workflows/fuzz.ymlfuzzes each target for 60s on PRs/pushes and 10min/target nightly (bounded to keep cost low). New crashers fail the job and upload the reproducer as an artifact.Notes
docs/papers/(Böhme et al., Coverage-based Greybox Fuzzing as Markov Chain, CCS 2016 — the AFLFast paper) anddocs/fuzzing.md.codegraph init+codegraph explore).🤖 Generated with Claude Code
https://claude.ai/code/session_01RTAMs4bpSZS77Xe3RQjv9P