ci: a fuzz crasher's failing input dies with the runner

Open Beginner friendly
#1,187 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
84/100
Issue type
Feature
Clarity
Clearly specified
Activity status
Active
Tech stack
github-actions, go
Domain
ci-cd, testing-qa

Research direction

Start with the fuzz-smoke step at .github/workflows/ci.yml:562, then find the fuzz-deep job in deep.yml and review how existing actions are pinned. Run the relevant workflow or inspect its conditions to verify that a failure artifact contains the new fuzz input while a green run uploads nothing. Done means both fuzz jobs upload the named testdata/fuzz files on failure.

Written by the indexing model from the issue text.

Description

kind/bug status/blocked

Problem

When the fuzz-smoke job finds a crasher, the one thing that run produced — the failing input — dies with the runner. Go's fuzzer writes it to the package's testdata/fuzz/<Target>/<hash> in the workspace and prints the path, but the job (.github/workflows/ci.yml:562, one step running make fuzz-smoke) has no artifact upload, so the file is unreachable the moment the job ends.

This is not hypothetical: run 33133571242 (job 98728489094, on 03e1efc6, PR #1186) found a real crasher — FuzzLoadSource, a nil-pointer panic inside goccy/go-yaml v1.19.2 reached through parseSourceWith — and wrote testdata/fuzz/FuzzLoadSource/0c45b3c87ce61506, 182 bytes that reproduce a process crash on hostile input. The log names the file; the file is gone. Triage now has to re-discover the input by fuzzing again or by reasoning backwards from the stack, which is exactly the machine-hours the corpus rules exist to save — CLAUDE.md already says a smoke crasher "is a real defect with a corpus entry to triage", and today CI deletes the corpus entry.

Desired outcome

On failure, the job uploads every new fuzz input so the triager can download it, reproduce locally, and commit it as the regression's corpus entry. Illustrative, not the landed shape — one step after the make fuzz-smoke step:

- uses: actions/upload-artifact@<pinned-sha> # pin by SHA like every other action here
  if: failure()
  with:
    name: fuzz-failing-inputs
    path: '**/testdata/fuzz/**'
    if-no-files-found: ignore
    retention-days: 14

Uploading the whole testdata/fuzz tree is fine: committed corpus entries come along, and the triager diffs against the checkout to find the new file — simpler and less fragile than teaching the step which files are new. The same step belongs on deep.yml's fuzz-deep job, where a lost input costs ten minutes of fuzzing per target rather than thirty seconds.

Constraints

  • Action pinned by commit SHA, matching every other action in these workflows.
  • if: failure() only — a green run uploads nothing and costs nothing.
  • Fuzz inputs are attacker-shaped bytes, not secrets; retention can be short since a triaged input gets committed as a corpus entry, which is the durable home.

Acceptance criteria

  • A fuzz-smoke failure's artifact contains the input the log names.
  • A green run produces no artifact.
  • Both ci.yml and deep.yml fuzz jobs carry the step.

Generated by Claude Code

Dominant language
Go
Stars
9
Forks
0
Avg merge
3h 3m
Merged PRs (30d)
509

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from picatz/flowstate

All issues in picatz/flowstate

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.