From 8239dffe51588ce1317a9e48595ee742d4ea04c7 Mon Sep 17 00:00:00 2001 From: Charalampos Mainas Date: Wed, 28 Oct 2026 16:45:19 +0000 Subject: [PATCH 1/5] ci: include .clusterfuzzlite in the Docker build context The root `.dockerignore` excludes everything not on its allowlist, and ClusterFuzzLite builds `.clusterfuzzlite/Dockerfile` with the repository root as context. `COPY .clusterfuzzlite/build.sh` therefore fails and the fuzzing workflows cannot build. Add the directory to the allowlist. PR: https://github.com/urunc-dev/urunc/pull/1175 Signed-off-by: Charalampos Mainas Reviewed-by: Anastassios Nanos Approved-by: Anastassios Nanos --- .dockerignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.dockerignore b/.dockerignore index fd1cd5d31..501f816a3 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,7 @@ # Keep .git: needed by git describe for version embedding. # COMMIT is also passed as a build-arg from CI to avoid a -dirty suffix. * +!/.clusterfuzzlite !/.git !/cmd !/deployment From ec0a4232f0c0a446a38ebb6f9d7b17cc9e890634 Mon Sep 17 00:00:00 2001 From: Charalampos Mainas Date: Wed, 28 Oct 2026 16:50:41 +0000 Subject: [PATCH 2/5] ci: fail the fuzzer build when a fuzz target is missing `compile_native_go_fuzzer_v2` only prints a message and exits 0 when it cannot find the fuzz function. After a rename the build would pass, no target would run and the workflow would stay green. To avoid that, check that the binary was produced. PR: https://github.com/urunc-dev/urunc/pull/1175 Signed-off-by: Charalampos Mainas Reviewed-by: Anastassios Nanos Approved-by: Anastassios Nanos --- .clusterfuzzlite/build.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.clusterfuzzlite/build.sh b/.clusterfuzzlite/build.sh index c569d503a..17a1fe382 100755 --- a/.clusterfuzzlite/build.sh +++ b/.clusterfuzzlite/build.sh @@ -17,4 +17,8 @@ # Only meant to run inside ClusterFuzzLite or OSS-Fuzz, which provide # compile_native_go_fuzzer_v2. -compile_native_go_fuzzer_v2 github.com/urunc-dev/urunc/pkg/unikontainers FuzzGetUnikernelConfig FuzzGetUnikernelConfig +fuzzer=FuzzGetUnikernelConfig +compile_native_go_fuzzer_v2 github.com/urunc-dev/urunc/pkg/unikontainers "$fuzzer" "$fuzzer" + +# compile_native_go_fuzzer_v2 exits 0 when it cannot find the function. +test -x "$OUT/$fuzzer" From b71b6998cbb96f90d7945f489cacfb66c50c3f7f Mon Sep 17 00:00:00 2001 From: Charalampos Mainas Date: Wed, 28 Oct 2026 17:05:35 +0000 Subject: [PATCH 3/5] ci: upload SARIF from fuzzing to code scanning - Upload `cifuzz-sarif/results.sarif` after batch runs. `output-sarif` only writes the file, so crashes never reached code scanning. - Upload it from a separate job. The ClusterFuzzLite actions run mutable `:v1` images, so the job running them keeps a read-only token, and only the upload job gets `security-events: write`. - Put batch and prune in one concurrency group. Each run downloads the corpus, changes it and uploads it again, so overlapping runs would overwrite each other's corpus. - Prune the corpus weekly instead of daily. Each run rebuilds the fuzzers, and the corpus of a single target grows slowly. - Rename `fuzz_nightly.yml` to `fuzz_batch.yml` to match `fuzz_prune.yml`. PR: https://github.com/urunc-dev/urunc/pull/1175 Signed-off-by: Charalampos Mainas Reviewed-by: Anastassios Nanos Approved-by: Anastassios Nanos --- .github/workflows/fuzz_batch.yml | 85 ++++++++++++++++++++++++++++++ .github/workflows/fuzz_nightly.yml | 36 ------------- .github/workflows/fuzz_prune.yml | 12 ++++- 3 files changed, 95 insertions(+), 38 deletions(-) create mode 100644 .github/workflows/fuzz_batch.yml delete mode 100644 .github/workflows/fuzz_nightly.yml diff --git a/.github/workflows/fuzz_batch.yml b/.github/workflows/fuzz_batch.yml new file mode 100644 index 000000000..8ddc9005a --- /dev/null +++ b/.github/workflows/fuzz_batch.yml @@ -0,0 +1,85 @@ +name: urunc fuzzing (batch) + +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * *' + +permissions: + contents: read + +# Shared with fuzz_prune.yml. Both download the corpus, change it and upload +# it again, so overlapping runs would overwrite each other's corpus. +concurrency: + group: clusterfuzzlite-corpus + cancel-in-progress: false + +jobs: + fuzz: + name: ClusterFuzzLite batch fuzzing + runs-on: ubuntu-24.04 + timeout-minutes: 60 + # The ClusterFuzzLite actions run mutable :v1 images, so this job only + # gets read access. The upload-sarif job uploads the results. + permissions: + contents: read + actions: read + outputs: + build: ${{ steps.build.outcome }} + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@351661ca32ac09a36dc5ee2d536e3128f2a3c8ed # v2.22.0 + with: + egress-policy: audit + + - name: Build fuzz targets + id: build + uses: google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1 # v1 + with: + language: go + + - name: Run fuzz targets + uses: google/clusterfuzzlite/actions/run_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1 # v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + language: go + mode: batch + fuzz-seconds: 1800 + output-sarif: true + + - name: Save SARIF results + if: always() && steps.build.outcome == 'success' + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: fuzz-sarif + path: cifuzz-sarif/results.sarif + if-no-files-found: error + retention-days: 7 + + upload-sarif: + name: Upload SARIF + needs: fuzz + # Also after a crash, which fails the fuzz job. + if: always() && needs.fuzz.outputs.build == 'success' + runs-on: ubuntu-24.04 + permissions: + contents: read + # for github/codeql-action/upload-sarif to upload SARIF results + security-events: write + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@351661ca32ac09a36dc5ee2d536e3128f2a3c8ed # v2.22.0 + with: + egress-policy: audit + + - name: Download SARIF results + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: fuzz-sarif + path: cifuzz-sarif + + - name: Upload SARIF + uses: github/codeql-action/upload-sarif@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1 + with: + sarif_file: cifuzz-sarif/results.sarif + checkout_path: cifuzz-sarif diff --git a/.github/workflows/fuzz_nightly.yml b/.github/workflows/fuzz_nightly.yml deleted file mode 100644 index 21a96bcd9..000000000 --- a/.github/workflows/fuzz_nightly.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: urunc fuzzing (nightly) - -on: - workflow_dispatch: - schedule: - - cron: '0 0 * * *' - -permissions: - contents: read - actions: read - security-events: write - -jobs: - fuzz: - name: ClusterFuzzLite batch fuzzing - runs-on: ubuntu-24.04 - timeout-minutes: 60 - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@351661ca32ac09a36dc5ee2d536e3128f2a3c8ed # v2.22.0 - with: - egress-policy: audit - - - name: Build fuzz targets - uses: google/clusterfuzzlite/actions/build_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1 # v1 - with: - language: go - - - name: Run fuzz targets - uses: google/clusterfuzzlite/actions/run_fuzzers@884713a6c30a92e5e8544c39945cd7cb630abcd1 # v1 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - language: go - mode: batch - fuzz-seconds: 1800 - output-sarif: true diff --git a/.github/workflows/fuzz_prune.yml b/.github/workflows/fuzz_prune.yml index 58c4cc40a..8f50b32c5 100644 --- a/.github/workflows/fuzz_prune.yml +++ b/.github/workflows/fuzz_prune.yml @@ -3,17 +3,25 @@ name: urunc fuzzing (corpus pruning) on: workflow_dispatch: schedule: - - cron: '30 13 * * *' + - cron: '30 13 * * 0' permissions: contents: read - actions: read + +# Shared with fuzz_batch.yml. Both download the corpus, change it and upload +# it again, so overlapping runs would overwrite each other's corpus. +concurrency: + group: clusterfuzzlite-corpus + cancel-in-progress: false jobs: prune: name: ClusterFuzzLite corpus pruning runs-on: ubuntu-24.04 timeout-minutes: 30 + permissions: + contents: read + actions: read steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@351661ca32ac09a36dc5ee2d536e3128f2a3c8ed # v2.22.0 From eb3138619b72e757c664e6fe8a75ad9caa0b1328 Mon Sep 17 00:00:00 2001 From: Charalampos Mainas Date: Wed, 28 Oct 2026 17:07:42 +0000 Subject: [PATCH 4/5] ci: track the ClusterFuzzLite base image with dependabot The `base-builder-go` image is pinned by digest and ships its own Go toolchain. Without updates it would eventually fall behind `go.mod`. PR: https://github.com/urunc-dev/urunc/pull/1175 Signed-off-by: Charalampos Mainas Reviewed-by: Anastassios Nanos Approved-by: Anastassios Nanos --- .github/dependabot.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c35a64525..dfc4c65be 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -13,6 +13,11 @@ updates: - "minor" - "patch" + - package-ecosystem: "docker" + directory: "/.clusterfuzzlite" + schedule: + interval: "weekly" + - package-ecosystem: "github-actions" directory: "/" schedule: From bb6c65c0b9e06ea5872227e8a2d8f2c63651ff4d Mon Sep 17 00:00:00 2001 From: Charalampos Mainas Date: Wed, 28 Oct 2026 17:15:04 +0000 Subject: [PATCH 5/5] ci: fix codeql-action version comment in scorecard workflow The pinned SHA is the `v4.39.1` tag, as in `codeql.yml`, not `v3.29.5`. PR: https://github.com/urunc-dev/urunc/pull/1175 Signed-off-by: Charalampos Mainas Reviewed-by: Anastassios Nanos Approved-by: Anastassios Nanos --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index a981364e9..4cc9077bb 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -78,6 +78,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v3.29.5 + uses: github/codeql-action/upload-sarif@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1 with: sarif_file: results.sarif