From 151033a81d4a94293c8e60dd974a06ef3ae1ffaf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 22 Sep 2026 00:44:47 +0000 Subject: [PATCH 1/5] ci: add build/validate-only workflow for ql/hotspots Co-authored-by: felickz <1760475+felickz@users.noreply.github.com> --- .github/workflows/hotspots-ci.yml | 216 ++++++++++++++++++++++++++++++ CONTRIBUTING.md | 6 + ql/hotspots/README.md | 44 +++++- 3 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/hotspots-ci.yml diff --git a/.github/workflows/hotspots-ci.yml b/.github/workflows/hotspots-ci.yml new file mode 100644 index 00000000..14425c12 --- /dev/null +++ b/.github/workflows/hotspots-ci.yml @@ -0,0 +1,216 @@ +name: "Hotspots Build/Validate" + +# Build/validate-only counterpart to `hotspots.yml` (which is a manual +# `workflow_dispatch` build *and publish* of the `githubsecuritylab/hotspots-*` packs). +# +# This workflow runs the exact same `ql/hotspots` pipeline - generate the per-language +# `Hotspots-.ql` queries with QL-4-QL, patch a copy of the `github/codeql` distribution, +# then build the resulting packs - but stops at `codeql pack create` and never publishes +# anything. It exists so PRs that touch `ql/hotspots/**` (notably Dependabot bumps of +# `ql/hotspots/requirements.txt`, which the generator/patch scripts run on) get the same +# CI signal every other pack in this repo already gets from `ci.yml`. +# +# Unlike `hotspots.yml`, which builds against the CodeQL CLI bundled with the CodeQL Action and +# `github/codeql@main`, this workflow is deliberately deterministic: it uses this repo's pinned +# `.codeqlversion` CLI and the matching `codeql-cli/v` tag of `github/codeql`, so a red +# run means *this PR* broke something rather than upstream moving underneath us. Use the +# `codeql-ref` `workflow_dispatch` input to validate against another ref (e.g. `main`) on demand. + +on: + pull_request: + branches: [main] + paths: + - "ql/hotspots/**" + - ".github/actions/install-codeql/**" + - ".github/workflows/hotspots-ci.yml" + workflow_dispatch: + inputs: + codeql-ref: + description: "github/codeql ref to build against (default: the codeql-cli/v<.codeqlversion> tag)" + required: false + type: string + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + # `swift` is deliberately absent: `generate-hotspots-queries.py` has no Swift support (it isn't + # in that script's `supported_languages`), so no `Hotspots-swift.ql` is ever generated and the + # patched Swift query pack has nothing to compile. `patch-codeql.py` still processes Swift (it + # prints `[-] Hotspots queries not found ...` and moves on), and `hotspots.yml` still publishes + # whatever that produces - validating it here would only ever fail on that known gap. + HOTSPOTS_LANGUAGES: '["cpp", "csharp", "go", "java", "javascript", "python", "ruby"]' + +jobs: + generate: + name: Generate hotspots queries + runs-on: ubuntu-latest + outputs: + codeql-ref: ${{ steps.ql-ref.outputs.ref }} + languages: ${{ steps.languages.outputs.languages }} + steps: + - uses: actions/checkout@v7 + + - name: Expose language matrix + id: languages + run: echo "languages=${HOTSPOTS_LANGUAGES}" >> "$GITHUB_OUTPUT" + + - name: Setup CodeQL + id: install-codeql + uses: ./.github/actions/install-codeql + + - name: Resolve github/codeql ref + id: ql-ref + env: + INPUT_REF: ${{ inputs.codeql-ref }} + CODEQL_CLI_VERSION: ${{ steps.install-codeql.outputs.codeql-cli-version }} + run: echo "ref=${INPUT_REF:-codeql-cli/v${CODEQL_CLI_VERSION}}" >> "$GITHUB_OUTPUT" + + - name: Checkout github/codeql + uses: actions/checkout@v7 + with: + repository: github/codeql + ref: ${{ steps.ql-ref.outputs.ref }} + path: codeql + + - name: Setup Python + uses: actions/setup-python@v7 + with: + # `requirements.txt` is `pip-compile --generate-hashes`d against Python 3.12 and pins + # cp312-only wheels, so the interpreter version has to match. + python-version: "3.12" + + - name: Install Python dependencies + run: python -m pip install --require-hashes -r ql/hotspots/requirements.txt + + - name: Validate scripts + run: | + python -m compileall -q ql/hotspots/scripts + python ql/hotspots/scripts/generate-hotspots-queries.py --help > /dev/null + python ql/hotspots/scripts/patch-codeql.py --help > /dev/null + + - name: Resolve github/codeql commit + id: ql-sha + run: echo "sha=$(git -C codeql rev-parse HEAD)" >> "$GITHUB_OUTPUT" + + - name: Cache QL extractor pack + id: cache-extractor + uses: actions/cache@v6 + with: + # The extractor pack is a pure function of the `github/codeql` commit it was built from, + # so it can be reused across runs. Building it is ~1 minute of `cargo build --release`. + path: codeql/ql/extractor-pack + key: ql-extractor-pack-${{ runner.os }}-${{ steps.ql-sha.outputs.sha }} + + - name: Build QL extractor + if: steps.cache-extractor.outputs.cache-hit != 'true' + working-directory: codeql/ql + run: ./scripts/create-extractor-pack.sh + + - name: Generate hotspots queries + run: | + python ql/hotspots/scripts/generate-hotspots-queries.py \ + --ql-extractor "$GITHUB_WORKSPACE/codeql/ql/extractor-pack" \ + --ql-path "$GITHUB_WORKSPACE/codeql" + + - name: Check generated queries + env: + LANGUAGES: ${{ env.HOTSPOTS_LANGUAGES }} + run: | + set -euo pipefail + failed=0 + for lang in $(echo "$LANGUAGES" | jq --raw-output '.[]'); do + query="ql/hotspots/output/Hotspots-${lang}.ql" + if [[ ! -f "$query" ]]; then + echo "::error::No query generated for ${lang} (${query} is missing)" + failed=1 + continue + fi + # A generated query with no `import ... as P` lines means the QL-4-QL generator + # matched no TaintTracking configurations at all for that language - the query would + # still compile, but it would be an empty, useless hotspots query. + imports=$(grep --count --extended-regexp '^import .* as P[0-9a-f]+' "$query" || true) + if [[ "$imports" -eq 0 ]]; then + echo "::error::${query} contains no taint-tracking configuration imports" + failed=1 + continue + fi + echo "[+] ${lang}: ${imports} configuration import(s)" + done + exit "$failed" + + - name: Upload generated hotspots queries + uses: actions/upload-artifact@v7 + with: + name: hotspots-generated-queries + path: ql/hotspots/output + if-no-files-found: error + + build-packs: + name: Build ${{ matrix.language }} hotspots packs + needs: generate + runs-on: ubuntu-latest + permissions: + contents: read + packages: read # `codeql pack install` reads from GHCR + + strategy: + fail-fast: false + matrix: + language: ${{ fromJSON(needs.generate.outputs.languages) }} + + steps: + - uses: actions/checkout@v7 + + - name: Setup CodeQL + uses: ./.github/actions/install-codeql + + - name: Checkout github/codeql + uses: actions/checkout@v7 + with: + repository: github/codeql + ref: ${{ needs.generate.outputs.codeql-ref }} + path: codeql + + - name: Setup Python + uses: actions/setup-python@v7 + with: + python-version: "3.12" + + - name: Install Python dependencies + run: python -m pip install --require-hashes -r ql/hotspots/requirements.txt + + - name: Download generated hotspots queries + uses: actions/download-artifact@v8 + with: + name: hotspots-generated-queries + path: ql/hotspots/output + + - name: Patch the CodeQL distribution + run: | + python ql/hotspots/scripts/patch-codeql.py \ + --hotspots "$GITHUB_WORKSPACE/ql/hotspots/output" \ + --ql "$GITHUB_WORKSPACE/codeql" \ + --dest "$GITHUB_WORKSPACE/codeql-patched" \ + --qlpack-version 0.0.0 + + - name: Build hotspots packs (no publish) + working-directory: codeql-patched + env: + GITHUB_TOKEN: ${{ github.token }} + LANGUAGE: ${{ matrix.language }} + # `pack create` is the compile step `pack publish` performs internally, so this is the + # same build `hotspots.yml` does - just without the upload to GHCR. + PACK_OUTPUT: ${{ runner.temp }}/hotspots-packs + run: | + set -euo pipefail + for dir in lib src; do + echo "::group::${LANGUAGE}/ql/${dir}" + codeql pack install "${LANGUAGE}/ql/${dir}" + codeql pack create "${LANGUAGE}/ql/${dir}" --output="${PACK_OUTPUT}" + echo "::endgroup::" + done diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eee0fa4b..c824483a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -440,6 +440,11 @@ coding agent) in the loop for the hard part — fixing whatever the new CLI brea > `codeql/ql` isn't a real package published to the registry or shipped in the CodeQL Bundle, so > `codeql pack upgrade`/the pinning script can never resolve it. This is a pre-existing, unrelated > quirk of that tool, not something the version-bump automation needs to (or can) fix. +> +> It does, however, get its own PR-time CI: [`hotspots-ci.yml`][hotspots-ci-workflow] runs the full +> generate → patch → `codeql pack create` pipeline (build/validate only, never publishing) on any PR +> touching `ql/hotspots/**`, so Dependabot bumps of `ql/hotspots/requirements.txt` and edits to the +> generator/patch scripts are covered. See `ql/hotspots/README.md`. > [!NOTE] > **Why `/ext` and `/ext-library-sources` are @@ -600,6 +605,7 @@ Please do get in touch (privacy@github.com) if you have any questions about this [update-codeql-version-workflow]: ./.github/workflows/update-codeql-version.yml [detect-codeql-release-workflow]: ./.github/workflows/detect-codeql-release.yml [copilot-setup-steps-workflow]: ./.github/workflows/copilot-setup-steps.yml +[hotspots-ci-workflow]: ./.github/workflows/hotspots-ci.yml [pin-codeql-library-versions-script]: ./.github/scripts/pin-codeql-library-versions.sh [build-publish-summary-script]: ./.github/scripts/build-publish-summary.sh [codeql-cli-binaries]: https://github.com/github/codeql-cli-binaries/releases diff --git a/ql/hotspots/README.md b/ql/hotspots/README.md index c8c1b273..501e278b 100644 --- a/ql/hotspots/README.md +++ b/ql/hotspots/README.md @@ -51,7 +51,49 @@ python scripts/generate-hotspots-queries.py --ql-extractor ~/src/codeql/ql/extra - Create a patched version of CodeQL distro (remove private modifiers and rename files/directories to remove whitespaces and dashes) ```bash -python scripts/patch-codeql.py --hotspots hotspots.csv --ql ~/src/codeql --dest /tmp/hotspots-distro --qlpack-version 0.0.1 +python scripts/patch-codeql.py --hotspots output --ql ~/src/codeql --dest /tmp/hotspots-distro --qlpack-version 0.0.1 ``` +(`--hotspots` takes the *directory* `generate-hotspots-queries.py` wrote to - `ql/hotspots/output`, containing `hotspots.csv` and the generated `Hotspots-.ql` files.) + - Run Hotspots query (eg: `/tmp/hotspots-distro/java/ql/src/Hotspots.ql`) + +- Build the patched packs without publishing them (this is what CI does, see below) + +```bash +cd /tmp/hotspots-distro +codeql pack install java/ql/lib && codeql pack create java/ql/lib --output=/tmp/hotspots-packs +codeql pack install java/ql/src && codeql pack create java/ql/src --output=/tmp/hotspots-packs +``` + +## CI + +Two workflows cover this directory: + +| Workflow | Trigger | What it does | +| ------------------------------------------------------------------------ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------- | +| [`hotspots.yml`](../../.github/workflows/hotspots.yml) | manual (`workflow_dispatch`, takes a version) | Generates, patches, **and publishes** the `githubsecuritylab/hotspots-*` packs to GHCR | +| [`hotspots-ci.yml`](../../.github/workflows/hotspots-ci.yml) | PRs touching `ql/hotspots/**`, or manual | Runs the same pipeline but stops at `codeql pack create` - **build/validate only, never publishes** | + +`hotspots-ci.yml` is what makes it safe to merge Dependabot bumps of `requirements.txt` (the +generator/patch scripts run on those dependencies) or edits to the scripts, queries or config here: + +- `generate` job: installs `requirements.txt` with `--require-hashes`, byte-compiles the scripts, + builds the QL extractor (cached per `github/codeql` commit), runs + `generate-hotspots-queries.py`, then fails if any supported language produced a missing or + empty (no taint-tracking configuration imports) `Hotspots-.ql`. The generated + queries are uploaded as a build artifact so they can be inspected on the PR. +- `build-packs` job: one matrix entry per language, so a failure is isolated to (and re-runnable + for) that language. Each runs `patch-codeql.py` over a fresh `github/codeql` checkout and then + `codeql pack install` + `codeql pack create` for that language's patched `lib` and `src` packs - + `pack create` is the compile step `pack publish` performs internally, so it is the same build + `hotspots.yml` does minus the upload. + +Unlike `hotspots.yml` (CodeQL Action bundle CLI + `github/codeql@main`), the CI workflow builds +against this repo's pinned [`.codeqlversion`](../../.codeqlversion) CLI and the matching +`codeql-cli/v` tag of `github/codeql`, so a failure points at the PR rather than at +upstream drift. Use the workflow's `codeql-ref` `workflow_dispatch` input to check against another +ref (e.g. `main`) before running a publish. + +Swift is excluded from CI: `generate-hotspots-queries.py` has no Swift support, so no +`Hotspots-swift.ql` is ever generated and there is nothing to compile for the patched Swift pack. From 82ce4ae0250dbc0300c5478dfeeef41260d5353c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 22 Sep 2026 00:46:06 +0000 Subject: [PATCH 2/5] ci: drop overridable codeql ref input to avoid cache-poisoning path Co-authored-by: felickz <1760475+felickz@users.noreply.github.com> --- .github/workflows/hotspots-ci.yml | 16 +++++++--------- ql/hotspots/README.md | 6 ++++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/hotspots-ci.yml b/.github/workflows/hotspots-ci.yml index 14425c12..dea96058 100644 --- a/.github/workflows/hotspots-ci.yml +++ b/.github/workflows/hotspots-ci.yml @@ -13,8 +13,12 @@ name: "Hotspots Build/Validate" # Unlike `hotspots.yml`, which builds against the CodeQL CLI bundled with the CodeQL Action and # `github/codeql@main`, this workflow is deliberately deterministic: it uses this repo's pinned # `.codeqlversion` CLI and the matching `codeql-cli/v` tag of `github/codeql`, so a red -# run means *this PR* broke something rather than upstream moving underneath us. Use the -# `codeql-ref` `workflow_dispatch` input to validate against another ref (e.g. `main`) on demand. +# run means *this PR* broke something rather than upstream moving underneath us. +# +# The `github/codeql` ref is deliberately not overridable by a `workflow_dispatch` input: this +# workflow both checks out that ref and writes to the Actions cache, so a caller-supplied ref +# would be untrusted code running in a cache-writing (and, on the default branch, +# cache-poisoning) context. on: pull_request: @@ -24,11 +28,6 @@ on: - ".github/actions/install-codeql/**" - ".github/workflows/hotspots-ci.yml" workflow_dispatch: - inputs: - codeql-ref: - description: "github/codeql ref to build against (default: the codeql-cli/v<.codeqlversion> tag)" - required: false - type: string permissions: contents: read @@ -66,9 +65,8 @@ jobs: - name: Resolve github/codeql ref id: ql-ref env: - INPUT_REF: ${{ inputs.codeql-ref }} CODEQL_CLI_VERSION: ${{ steps.install-codeql.outputs.codeql-cli-version }} - run: echo "ref=${INPUT_REF:-codeql-cli/v${CODEQL_CLI_VERSION}}" >> "$GITHUB_OUTPUT" + run: echo "ref=codeql-cli/v${CODEQL_CLI_VERSION}" >> "$GITHUB_OUTPUT" - name: Checkout github/codeql uses: actions/checkout@v7 diff --git a/ql/hotspots/README.md b/ql/hotspots/README.md index 501e278b..b64b213e 100644 --- a/ql/hotspots/README.md +++ b/ql/hotspots/README.md @@ -92,8 +92,10 @@ generator/patch scripts run on those dependencies) or edits to the scripts, quer Unlike `hotspots.yml` (CodeQL Action bundle CLI + `github/codeql@main`), the CI workflow builds against this repo's pinned [`.codeqlversion`](../../.codeqlversion) CLI and the matching `codeql-cli/v` tag of `github/codeql`, so a failure points at the PR rather than at -upstream drift. Use the workflow's `codeql-ref` `workflow_dispatch` input to check against another -ref (e.g. `main`) before running a publish. +upstream drift. That ref is intentionally not overridable from a workflow input: the workflow +checks it out and writes to the Actions cache, so an arbitrary caller-supplied ref would be +untrusted code in a cache-writing context. To validate against `github/codeql@main` before a +publish, run `hotspots.yml` (or the commands above) instead. Swift is excluded from CI: `generate-hotspots-queries.py` has no Swift support, so no `Hotspots-swift.ql` is ever generated and there is nothing to compile for the patched Swift pack. From 70b58e2a2a847d3f508b7b99f1de4d6f8e287543 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 22 Sep 2026 00:47:50 +0000 Subject: [PATCH 3/5] ci: avoid Actions cache writes in hotspots CI jobs Co-authored-by: felickz <1760475+felickz@users.noreply.github.com> --- .github/actions/install-codeql/action.yml | 10 ++++++++ .github/workflows/hotspots-ci.yml | 31 ++++++++++------------- ql/hotspots/README.md | 10 ++++---- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/.github/actions/install-codeql/action.yml b/.github/actions/install-codeql/action.yml index 54ecdbea..71570910 100644 --- a/.github/actions/install-codeql/action.yml +++ b/.github/actions/install-codeql/action.yml @@ -2,6 +2,15 @@ name: Setup CodeQL CLI description: | Install a CodeQL CLI or re-use an existing one from the cache and it to the path. +inputs: + cache: + description: | + Whether to restore/save the downloaded CLI from the Actions cache. Set to "false" in + workflows that check out and execute code from another repository (e.g. `github/codeql`), + so the job never writes to a cache that is shared with the default branch. + required: false + default: "true" + outputs: codeql-cli-version: description: "The version of the CodeQL CLI that was installed or retrieved from cache" @@ -21,6 +30,7 @@ runs: - name: Cache CodeQL id: cache-codeql + if: inputs.cache != 'false' uses: actions/cache@v6 with: # A list of files, directories, and wildcard patterns to cache and restore diff --git a/.github/workflows/hotspots-ci.yml b/.github/workflows/hotspots-ci.yml index dea96058..87a6f6e4 100644 --- a/.github/workflows/hotspots-ci.yml +++ b/.github/workflows/hotspots-ci.yml @@ -15,10 +15,10 @@ name: "Hotspots Build/Validate" # `.codeqlversion` CLI and the matching `codeql-cli/v` tag of `github/codeql`, so a red # run means *this PR* broke something rather than upstream moving underneath us. # -# The `github/codeql` ref is deliberately not overridable by a `workflow_dispatch` input: this -# workflow both checks out that ref and writes to the Actions cache, so a caller-supplied ref -# would be untrusted code running in a cache-writing (and, on the default branch, -# cache-poisoning) context. +# The `github/codeql` ref is deliberately not overridable by a `workflow_dispatch` input, and no +# job here writes to the Actions cache: this workflow checks out and executes code from another +# repository, and on the default branch (`workflow_dispatch`) a cache write from such a job is a +# cache-poisoning vector. on: pull_request: @@ -61,6 +61,10 @@ jobs: - name: Setup CodeQL id: install-codeql uses: ./.github/actions/install-codeql + with: + # No cache writes in a job that checks out and executes code from another repository + # (`github/codeql`): on the default branch that would be a cache-poisoning vector. + cache: "false" - name: Resolve github/codeql ref id: ql-ref @@ -91,21 +95,10 @@ jobs: python ql/hotspots/scripts/generate-hotspots-queries.py --help > /dev/null python ql/hotspots/scripts/patch-codeql.py --help > /dev/null - - name: Resolve github/codeql commit - id: ql-sha - run: echo "sha=$(git -C codeql rev-parse HEAD)" >> "$GITHUB_OUTPUT" - - - name: Cache QL extractor pack - id: cache-extractor - uses: actions/cache@v6 - with: - # The extractor pack is a pure function of the `github/codeql` commit it was built from, - # so it can be reused across runs. Building it is ~1 minute of `cargo build --release`. - path: codeql/ql/extractor-pack - key: ql-extractor-pack-${{ runner.os }}-${{ steps.ql-sha.outputs.sha }} - + # Deliberately not cached: this job checks out and runs code from `github/codeql`, and a + # cache write here would be shared with the default branch. The build is ~1 minute of + # `cargo build --release`. - name: Build QL extractor - if: steps.cache-extractor.outputs.cache-hit != 'true' working-directory: codeql/ql run: ./scripts/create-extractor-pack.sh @@ -166,6 +159,8 @@ jobs: - name: Setup CodeQL uses: ./.github/actions/install-codeql + with: + cache: "false" # see the matching comment in the `generate` job - name: Checkout github/codeql uses: actions/checkout@v7 diff --git a/ql/hotspots/README.md b/ql/hotspots/README.md index b64b213e..eb4b275e 100644 --- a/ql/hotspots/README.md +++ b/ql/hotspots/README.md @@ -79,7 +79,7 @@ Two workflows cover this directory: generator/patch scripts run on those dependencies) or edits to the scripts, queries or config here: - `generate` job: installs `requirements.txt` with `--require-hashes`, byte-compiles the scripts, - builds the QL extractor (cached per `github/codeql` commit), runs + builds the QL extractor, runs `generate-hotspots-queries.py`, then fails if any supported language produced a missing or empty (no taint-tracking configuration imports) `Hotspots-.ql`. The generated queries are uploaded as a build artifact so they can be inspected on the PR. @@ -92,10 +92,10 @@ generator/patch scripts run on those dependencies) or edits to the scripts, quer Unlike `hotspots.yml` (CodeQL Action bundle CLI + `github/codeql@main`), the CI workflow builds against this repo's pinned [`.codeqlversion`](../../.codeqlversion) CLI and the matching `codeql-cli/v` tag of `github/codeql`, so a failure points at the PR rather than at -upstream drift. That ref is intentionally not overridable from a workflow input: the workflow -checks it out and writes to the Actions cache, so an arbitrary caller-supplied ref would be -untrusted code in a cache-writing context. To validate against `github/codeql@main` before a -publish, run `hotspots.yml` (or the commands above) instead. +upstream drift. That ref is intentionally not overridable from a workflow input, and the workflow +never writes to the Actions cache, because it checks out and executes code from another +repository. To validate against `github/codeql@main` before a publish, run `hotspots.yml` (or the +commands above) instead. Swift is excluded from CI: `generate-hotspots-queries.py` has no Swift support, so no `Hotspots-swift.ql` is ever generated and there is nothing to compile for the patched Swift pack. From 47d5be1efd33b66479a6d61ad7b794197bbec7e8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 22 Sep 2026 00:49:21 +0000 Subject: [PATCH 4/5] ci: confine hotspots CI to pull_request, revert install-codeql change Co-authored-by: felickz <1760475+felickz@users.noreply.github.com> --- .github/actions/install-codeql/action.yml | 10 ---------- .github/workflows/hotspots-ci.yml | 23 +++++++++-------------- ql/hotspots/README.md | 10 +++++----- 3 files changed, 14 insertions(+), 29 deletions(-) diff --git a/.github/actions/install-codeql/action.yml b/.github/actions/install-codeql/action.yml index 71570910..54ecdbea 100644 --- a/.github/actions/install-codeql/action.yml +++ b/.github/actions/install-codeql/action.yml @@ -2,15 +2,6 @@ name: Setup CodeQL CLI description: | Install a CodeQL CLI or re-use an existing one from the cache and it to the path. -inputs: - cache: - description: | - Whether to restore/save the downloaded CLI from the Actions cache. Set to "false" in - workflows that check out and execute code from another repository (e.g. `github/codeql`), - so the job never writes to a cache that is shared with the default branch. - required: false - default: "true" - outputs: codeql-cli-version: description: "The version of the CodeQL CLI that was installed or retrieved from cache" @@ -30,7 +21,6 @@ runs: - name: Cache CodeQL id: cache-codeql - if: inputs.cache != 'false' uses: actions/cache@v6 with: # A list of files, directories, and wildcard patterns to cache and restore diff --git a/.github/workflows/hotspots-ci.yml b/.github/workflows/hotspots-ci.yml index 87a6f6e4..2d282712 100644 --- a/.github/workflows/hotspots-ci.yml +++ b/.github/workflows/hotspots-ci.yml @@ -15,10 +15,13 @@ name: "Hotspots Build/Validate" # `.codeqlversion` CLI and the matching `codeql-cli/v` tag of `github/codeql`, so a red # run means *this PR* broke something rather than upstream moving underneath us. # -# The `github/codeql` ref is deliberately not overridable by a `workflow_dispatch` input, and no -# job here writes to the Actions cache: this workflow checks out and executes code from another -# repository, and on the default branch (`workflow_dispatch`) a cache write from such a job is a -# cache-poisoning vector. +# Security note: this workflow checks out and executes code from another repository +# (`github/codeql`), so it is deliberately confined to the `pull_request` event - where the Actions +# cache scope is the PR's own branch - with no `workflow_dispatch` (which would run it on the +# default branch, whose cache is shared with every other workflow). For the same reason the +# `github/codeql` ref is always derived from `.codeqlversion` rather than a caller-supplied input. +# To build against a different `github/codeql` ref, +# run the `hotspots.yml` publish workflow or the pipeline locally (see `ql/hotspots/README.md`). on: pull_request: @@ -27,7 +30,6 @@ on: - "ql/hotspots/**" - ".github/actions/install-codeql/**" - ".github/workflows/hotspots-ci.yml" - workflow_dispatch: permissions: contents: read @@ -61,10 +63,6 @@ jobs: - name: Setup CodeQL id: install-codeql uses: ./.github/actions/install-codeql - with: - # No cache writes in a job that checks out and executes code from another repository - # (`github/codeql`): on the default branch that would be a cache-poisoning vector. - cache: "false" - name: Resolve github/codeql ref id: ql-ref @@ -95,9 +93,8 @@ jobs: python ql/hotspots/scripts/generate-hotspots-queries.py --help > /dev/null python ql/hotspots/scripts/patch-codeql.py --help > /dev/null - # Deliberately not cached: this job checks out and runs code from `github/codeql`, and a - # cache write here would be shared with the default branch. The build is ~1 minute of - # `cargo build --release`. + # ~1 minute of `cargo build --release`; deliberately not cached, to keep this job free of + # Actions cache writes of anything derived from the `github/codeql` checkout. - name: Build QL extractor working-directory: codeql/ql run: ./scripts/create-extractor-pack.sh @@ -159,8 +156,6 @@ jobs: - name: Setup CodeQL uses: ./.github/actions/install-codeql - with: - cache: "false" # see the matching comment in the `generate` job - name: Checkout github/codeql uses: actions/checkout@v7 diff --git a/ql/hotspots/README.md b/ql/hotspots/README.md index eb4b275e..8df1b468 100644 --- a/ql/hotspots/README.md +++ b/ql/hotspots/README.md @@ -73,7 +73,7 @@ Two workflows cover this directory: | Workflow | Trigger | What it does | | ------------------------------------------------------------------------ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | [`hotspots.yml`](../../.github/workflows/hotspots.yml) | manual (`workflow_dispatch`, takes a version) | Generates, patches, **and publishes** the `githubsecuritylab/hotspots-*` packs to GHCR | -| [`hotspots-ci.yml`](../../.github/workflows/hotspots-ci.yml) | PRs touching `ql/hotspots/**`, or manual | Runs the same pipeline but stops at `codeql pack create` - **build/validate only, never publishes** | +| [`hotspots-ci.yml`](../../.github/workflows/hotspots-ci.yml) | PRs touching `ql/hotspots/**` | Runs the same pipeline but stops at `codeql pack create` - **build/validate only, never publishes** | `hotspots-ci.yml` is what makes it safe to merge Dependabot bumps of `requirements.txt` (the generator/patch scripts run on those dependencies) or edits to the scripts, queries or config here: @@ -92,10 +92,10 @@ generator/patch scripts run on those dependencies) or edits to the scripts, quer Unlike `hotspots.yml` (CodeQL Action bundle CLI + `github/codeql@main`), the CI workflow builds against this repo's pinned [`.codeqlversion`](../../.codeqlversion) CLI and the matching `codeql-cli/v` tag of `github/codeql`, so a failure points at the PR rather than at -upstream drift. That ref is intentionally not overridable from a workflow input, and the workflow -never writes to the Actions cache, because it checks out and executes code from another -repository. To validate against `github/codeql@main` before a publish, run `hotspots.yml` (or the -commands above) instead. +upstream drift. Because it checks out and executes code from another repository, the workflow is +confined to the `pull_request` event (where the Actions cache scope is the PR branch) and the ref +is not overridable from a workflow input. To validate against +`github/codeql@main` before a publish, run `hotspots.yml` (or the commands above) instead. Swift is excluded from CI: `generate-hotspots-queries.py` has no Swift support, so no `Hotspots-swift.ql` is ever generated and there is nothing to compile for the patched Swift pack. From 1f0020140e9a0b6bdb1e67cc72a425b364f858dd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 22 Sep 2026 15:06:45 +0000 Subject: [PATCH 5/5] Fix hotspots-ci.yml: persist-credentials: false on checkouts, add .codeqlversion to trigger paths Co-authored-by: felickz <1760475+felickz@users.noreply.github.com> --- .github/workflows/hotspots-ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/hotspots-ci.yml b/.github/workflows/hotspots-ci.yml index 2d282712..8c05a4eb 100644 --- a/.github/workflows/hotspots-ci.yml +++ b/.github/workflows/hotspots-ci.yml @@ -30,6 +30,7 @@ on: - "ql/hotspots/**" - ".github/actions/install-codeql/**" - ".github/workflows/hotspots-ci.yml" + - ".codeqlversion" permissions: contents: read @@ -55,6 +56,8 @@ jobs: languages: ${{ steps.languages.outputs.languages }} steps: - uses: actions/checkout@v7 + with: + persist-credentials: false - name: Expose language matrix id: languages @@ -76,6 +79,7 @@ jobs: repository: github/codeql ref: ${{ steps.ql-ref.outputs.ref }} path: codeql + persist-credentials: false - name: Setup Python uses: actions/setup-python@v7 @@ -153,6 +157,8 @@ jobs: steps: - uses: actions/checkout@v7 + with: + persist-credentials: false - name: Setup CodeQL uses: ./.github/actions/install-codeql @@ -163,6 +169,7 @@ jobs: repository: github/codeql ref: ${{ needs.generate.outputs.codeql-ref }} path: codeql + persist-credentials: false - name: Setup Python uses: actions/setup-python@v7