Skip to content

Fuzz

Fuzz #1

Workflow file for this run

name: Fuzz
on:
schedule:
- cron: "0 3 * * *" # 03:00 UTC daily
workflow_dispatch:
inputs:
duration:
description: Seconds to fuzz (-V)
required: false
default: "1200"
permissions:
contents: read
concurrency:
group: fuzz
cancel-in-progress: true
jobs:
fuzz:
name: American Fuzzy Lop (fuzzer)
runs-on: ubuntu-26.04
timeout-minutes: 45
env:
DURATION: ${{ github.event.inputs.duration || '1200' }}
AFL_NO_AFFINITY: "1"
steps:
- uses: actions/checkout@v7
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
cache: false
rustflags: ""
# No cargo cache on purpose (a restored ~/.cargo corrupts cargo-afl's state); install also builds the AFL LLVM runtime, so don't rebuild it.
- name: Install cargo-afl
run: cargo install cargo-afl
- name: Fuzz
working-directory: fuzz
run: bash ./deploy.sh
- name: Triage
working-directory: fuzz
run: |
shopt -s nullglob
crashes=(out/*/crashes*/id:*)
hangs=(out/*/hangs*/id:*)
for f in "${hangs[@]}"; do echo "::warning::hang $(basename "$f")"; done
if (( ${#crashes[@]} )); then
for f in "${crashes[@]}"; do echo "::error::crash $f"; cat "$f"; echo; done
exit 1
fi
echo "no crashes (${#hangs[@]} hangs)"
# AFL findings use colons in names (rejected by upload-artifact), so tar them; create an empty archive if out/ doesn't exist yet.
- name: Package findings
if: always()
run: |
shopt -s nullglob
dirs=(fuzz/out/*/crashes* fuzz/out/*/hangs*)
if (( ${#dirs[@]} )); then
tar -czf findings.tar.gz "${dirs[@]}"
else
echo "no findings to package"
tar -czf findings.tar.gz --files-from /dev/null
fi
- name: Upload findings
if: always()
uses: actions/upload-artifact@v7
with:
name: fuzz-findings
path: findings.tar.gz
retention-days: 14