Repository navigation
Security Deep #306
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
| name: Security Deep | |
| # LAB-1140 PROOF BRANCH — trimmed to the atheris-fuzzing job only, byte-identical | |
| # to the job on the fix branch (lab-1140-atheris-honest-red), so proof runs do | |
| # not burn hours of unrelated kani/miri/sanitizer time on the self-hosted pool. | |
| # Never to be merged. | |
| on: | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| atheris-fuzzing: | |
| name: Atheris Python-Rust Fuzzing | |
| runs-on: cachekit | |
| timeout-minutes: 60 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| # Pin to 3.11: atheris 2.3.0's newest prebuilt wheel is cp311. On a newer | |
| # interpreter uv builds atheris from sdist, which needs clang + libFuzzer | |
| # (find_libfuzzer.sh) — absent on the self-hosted runner, so install fails | |
| # before any fuzzing runs. Both uv sync and uv run must pin, or uv run | |
| # re-resolves to a different interpreter and re-triggers the source build. | |
| - name: Install dependencies | |
| run: | | |
| uv sync --group dev --group fuzz --python 3.11 | |
| # Exit-code contract — no `|| true`, every non-zero exit fails the job. | |
| # (scripts/fuzz-python.sh carries the same contract for local runs; keep | |
| # the budgets and flags in the two files in sync.) | |
| # - Pass is libFuzzer exiting 0 when -max_total_time=600 expires cleanly. | |
| # - A crash, OOM, or uncaught Python exception exits non-zero and fails | |
| # the job. atheris.Setup(sys.argv, ...) forwards flags to libFuzzer, so | |
| # -artifact_prefix drops the reproducer in tests/fuzzing/artifacts/. | |
| # No corpus dir is passed, so that directory only ever holds crash | |
| # artifacts — a file there is always a finding, never corpus growth. | |
| # - A hung input is caught by libFuzzer's own per-input watchdog | |
| # (-timeout=60), which writes a timeout-* reproducer and exits | |
| # non-zero. `timeout -k 30s 15m` is the backstop for hangs in native | |
| # code where that watchdog can't fire: exit 124 is a deliberate | |
| # FAILURE, not budget exhaustion — the fuzz budget is 600 s and budget | |
| # exhaustion exits 0 above, so a target still alive at 15 min is hung | |
| # (and libFuzzer traps SIGTERM, hence the -k hard kill). | |
| # - Zero matched targets fails the job: a glob that stops matching must | |
| # not "pass" having fuzzed nothing (LAB-1136 post-mortem pattern). | |
| - name: Run Atheris fuzz targets (10 min each) | |
| run: | | |
| mkdir -p tests/fuzzing/artifacts | |
| shopt -s nullglob | |
| targets=(tests/fuzzing/fuzz_*.py) | |
| if [ "${#targets[@]}" -eq 0 ]; then | |
| echo "::error::no Atheris targets matched tests/fuzzing/fuzz_*.py — refusing to pass having fuzzed nothing" | |
| exit 1 | |
| fi | |
| for fuzz_target in "${targets[@]}"; do | |
| echo "Fuzzing $fuzz_target..." | |
| timeout -k 30s 15m uv run --python 3.11 python "$fuzz_target" \ | |
| -max_total_time=600 -timeout=60 -artifact_prefix=tests/fuzzing/artifacts/ | |
| done | |
| # No "Report fuzzing results" step: now that `|| true` is gone, a crash | |
| # fails its own fuzz step, so a trailing check could only ever run in the | |
| # no-crash case and print ✅ — a named green step incapable of failing, | |
| # the manufactured-evidence pattern the Extended Fuzzing job above already | |
| # removed. (The old gate also inspected tests/fuzzing/corpus/, a directory | |
| # nothing ever wrote to.) The fuzz steps' exit codes are the signal; this | |
| # upload preserves the reproducer, which would otherwise die with the | |
| # ephemeral runner. | |
| - name: Upload crash artifacts | |
| if: failure() | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 | |
| with: | |
| name: atheris-crash-artifacts | |
| path: tests/fuzzing/artifacts/ | |
| # Public repo: a crash reproducer is a ready-made PoC for anyone while | |
| # it is retrievable. 7 days covers triage of a nightly red without | |
| # leaving a month-long public exploit window. | |
| retention-days: 7 | |
| if-no-files-found: warn |