From 308a907875221e7902ce7a5627372ea8792a5bc3 Mon Sep 17 00:00:00 2001 From: Chris Fuka Date: Wed, 22 Jul 2026 07:57:56 -0500 Subject: [PATCH 1/2] ci: add ruff, zizmor, and CodeQL static analysis Wire three static-analysis passes into CI and harden the workflows so they run clean against them: - ruff (pyflakes F rules) and zizmor (GitHub Actions security auditor) run in the ci.yml static job. CodeQL scans Python and the native C sources (the DLL injector, cryptbase RNG stub, and XCurl CA shim, cross-compiled with mingw so the extractor observes them) via a new codeql.yml. - Harden every workflow to pass zizmor: set persist-credentials: false on all actions/checkout steps, and stop expanding workflow_dispatch inputs (force_rebuild / publish / channel) inline in run blocks, binding them to env vars instead (the template-injection findings). - Drop an unused import ruff flagged in tests/test_auth_settings.py. Validated locally: ruff, zizmor, and actionlint all clean; 221 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_014pmkUWS6teoMZUUnMJG7Gr --- .github/workflows/build-app.yml | 8 +++- .github/workflows/build-engine.yml | 2 + .github/workflows/build-vkd3d.yml | 2 + .github/workflows/build-winegdk.yml | 2 + .github/workflows/build-xcurl.yml | 2 + .github/workflows/ci.yml | 14 +++++++ .github/workflows/codeql.yml | 62 +++++++++++++++++++++++++++++ .github/workflows/release.yml | 9 ++++- tests/test_auth_settings.py | 1 - 9 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/build-app.yml b/.github/workflows/build-app.yml index 0ab7ef2..21ebaa5 100644 --- a/.github/workflows/build-app.yml +++ b/.github/workflows/build-app.yml @@ -55,6 +55,8 @@ jobs: BOL_ALLOW_PARTIAL_ARTIFACTS: ${{ vars.BOL_ALLOW_PARTIAL_ARTIFACTS }} steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Install the packaging toolchain run: | @@ -158,6 +160,8 @@ jobs: GH_TOKEN: ${{ github.token }} steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Download the built artifacts uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: @@ -176,6 +180,8 @@ jobs: dist/BedrockOnLinux-*-inputs.sha256 - name: Compute release metadata + bill of materials + env: + CHANNEL_INPUT: ${{ inputs.channel }} run: | ver="$(grep -m1 '^VERSION = ' bol/config.py | cut -d'"' -f2)" eng_rev="$(grep -m1 '^WINEGDK_BUILD_REV = ' bol/config.py | cut -d'"' -f2)" @@ -185,7 +191,7 @@ jobs: xcurl_rev="$(grep -m1 '^OPENSSL_XCURL_REV = ' bol/config.py | cut -d'"' -f2)" vkd3d_hashes="$(grep -m1 '^VKD3D_OUTPUT_HASHES_SHA256=' \ third_party/vkd3d-proton-universal/provenance.env | cut -d= -f2 | tr -d "'\"")" - channel="${{ inputs.channel || 'release' }}" + channel="${CHANNEL_INPUT:-release}" if [ "$channel" = "nightly" ]; then # Rolling nightly: one release/tag, moved to HEAD each run (see the # "Roll the nightly tag" step). Date + short commit in the name give diff --git a/.github/workflows/build-engine.yml b/.github/workflows/build-engine.yml index 4759b8d..46bab8a 100644 --- a/.github/workflows/build-engine.yml +++ b/.github/workflows/build-engine.yml @@ -81,6 +81,8 @@ jobs: GH_TOKEN: ${{ github.token }} steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Install packaging tools run: | diff --git a/.github/workflows/build-vkd3d.yml b/.github/workflows/build-vkd3d.yml index 14546c3..862d932 100644 --- a/.github/workflows/build-vkd3d.yml +++ b/.github/workflows/build-vkd3d.yml @@ -47,6 +47,8 @@ jobs: sha256: ${{ steps.pack.outputs.sha256 }} steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Build universal vkd3d-proton in a pinned Trixie container run: | diff --git a/.github/workflows/build-winegdk.yml b/.github/workflows/build-winegdk.yml index 5c723a2..00923ab 100644 --- a/.github/workflows/build-winegdk.yml +++ b/.github/workflows/build-winegdk.yml @@ -50,6 +50,8 @@ jobs: short: ${{ steps.pack.outputs.short }} steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Prepare work area on the large /mnt volume run: | diff --git a/.github/workflows/build-xcurl.yml b/.github/workflows/build-xcurl.yml index 6e67b2c..446b3da 100644 --- a/.github/workflows/build-xcurl.yml +++ b/.github/workflows/build-xcurl.yml @@ -49,6 +49,8 @@ jobs: rev: ${{ steps.build.outputs.rev }} steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Build the set from source in a pinned Trixie container run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 320d630..b882a88 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,8 @@ jobs: timeout-minutes: 15 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Run the test suite run: | python3 -m venv .venv @@ -34,6 +36,8 @@ jobs: timeout-minutes: 15 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Byte-compile the package run: python3 -m compileall -q bol @@ -54,6 +58,14 @@ jobs: tar -xzf actionlint.tar.gz actionlint ./actionlint -color + - name: Lint Python (ruff, pyflakes rules) + run: pipx run --spec 'ruff==0.14.3' ruff check --select F bol/ tests/ + + - name: Audit the workflows (zizmor) + env: + GH_TOKEN: ${{ github.token }} + run: pipx run --spec 'zizmor==1.5.2' zizmor --persona=regular .github/workflows/ + cryptbase: # Wine runtime test for the from-source cryptbase RNG stub: proves # SystemFunction036 returns varied random bytes and does not recurse to a @@ -62,6 +74,8 @@ jobs: timeout-minutes: 15 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Run scripts/test-cryptbase.sh in a pinned Trixie container run: | docker run --rm -v "$PWD:/repo" -w /repo \ diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..0ec3223 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,62 @@ +# CodeQL static analysis for the Python launcher and the native C sources +# (the DLL injector, the cryptbase RNG stub, and the XCurl CA shim: the +# highest-risk code in the tree). Python needs no build; the C sources are +# cross-compiled with mingw between init and analyze so the extractor observes +# them. Results surface in the repository's code-scanning tab. +name: CodeQL + +on: + push: + branches: [main] + pull_request: + schedule: + - cron: "0 8 * * 1" # weekly, Monday ~08:00 UTC + +permissions: + contents: read + +concurrency: + group: codeql-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + runs-on: ubuntu-24.04 + timeout-minutes: 30 + permissions: + security-events: write + contents: read + strategy: + fail-fast: false + matrix: + include: + - language: python + build-mode: none + - language: c-cpp + build-mode: manual + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false + + - name: Initialize CodeQL + uses: github/codeql-action/init@3b0bd1d116c0bde30213346b22d4f634d96a2fb0 # v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + + - name: Build the native C sources for the extractor + if: matrix.build-mode == 'manual' + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends gcc-mingw-w64-x86-64 + CC=x86_64-w64-mingw32-gcc + "$CC" -c -O2 -mrdrnd src/cryptbase-stub.c -o "$RUNNER_TEMP/cryptbase.o" + "$CC" -c -O2 src/xcurl-cashim.c -o "$RUNNER_TEMP/xcurl-cashim.o" + "$CC" -c -O2 src/injector.c -o "$RUNNER_TEMP/injector.o" + + - name: Perform CodeQL analysis + uses: github/codeql-action/analyze@3b0bd1d116c0bde30213346b22d4f634d96a2fb0 # v3 + with: + category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 95a0975..f8ca8aa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -54,13 +54,18 @@ jobs: publish: ${{ steps.probe.outputs.publish }} steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Resolve pins and decide reuse-or-build per tier id: probe + env: + FORCE_REBUILD: ${{ inputs.force_rebuild }} + PUBLISH_INPUT: ${{ inputs.publish }} run: | set -euo pipefail repo="${{ github.repository }}" - force="${{ inputs.force_rebuild || 'false' }}" + force="${FORCE_REBUILD:-false}" cfg=bol/config.py xrev="$(grep -m1 '^OPENSSL_XCURL_REV = ' $cfg | cut -d'"' -f2)" xsha="$(grep -m1 '^OPENSSL_XCURL_ARCHIVE_SHA256 = ' $cfg | cut -d'"' -f2)" @@ -94,7 +99,7 @@ jobs: if [ "${{ github.event_name }}" = "schedule" ]; then channel=nightly; publish=true else - channel=release; publish="${{ inputs.publish }}" + channel=release; publish="$PUBLISH_INPUT" fi { echo "build_xcurl=$bx" diff --git a/tests/test_auth_settings.py b/tests/test_auth_settings.py index 48fcc32..b0d2d7e 100644 --- a/tests/test_auth_settings.py +++ b/tests/test_auth_settings.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: MIT import json -import os import stat import tempfile import unittest From 1a9964fdf10ff2410475a68a2eab1ad1f32c1d08 Mon Sep 17 00:00:00 2001 From: Chris Fuka Date: Wed, 22 Jul 2026 08:06:59 -0500 Subject: [PATCH 2/2] ci: pin codeql-action to its commit SHA (zizmor impostor-commit) codeql-action v3 is an annotated tag, so the git-ref API returns the tag object SHA (3b0bd1d), not a commit. zizmor's online impostor-commit audit correctly flags pinning to it as "a commit that doesn't belong to the repo". Pin the underlying commit (4187e74) the tag resolves to. This only surfaces with an API token, hence it passed locally (offline) but failed in CI where GH_TOKEN enables zizmor's online audits. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_014pmkUWS6teoMZUUnMJG7Gr --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0ec3223..311d8de 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -41,7 +41,7 @@ jobs: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@3b0bd1d116c0bde30213346b22d4f634d96a2fb0 # v3 + uses: github/codeql-action/init@4187e74d05793876e9989daffde9c3e66b4acd07 # v3 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -57,6 +57,6 @@ jobs: "$CC" -c -O2 src/injector.c -o "$RUNNER_TEMP/injector.o" - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@3b0bd1d116c0bde30213346b22d4f634d96a2fb0 # v3 + uses: github/codeql-action/analyze@4187e74d05793876e9989daffde9c3e66b4acd07 # v3 with: category: "/language:${{ matrix.language }}"