Compare commits

..

20 Commits

Author SHA1 Message Date
Sam Robson
913e1bb775 Merge pull request #4283 from github/sam-robson/decode-diff-informed-sarif-uris
fix: decode SARIF location URIs in diff-informed alert filtering
2026-11-03 19:47:09 +00:00
Michael B. Gale
c5320e3a8a Merge pull request #4288 from github/dependabot/npm_and_yarn/node-forge-1.4.1
Bump node-forge from 1.4.0 to 1.4.1
2026-11-03 15:53:37 +00:00
Michael B. Gale
875ac0c36c Merge pull request #4287 from github/dependabot/npm_and_yarn/pr-checks/glob-14.0.3
Bump glob from 13.0.6 to 14.0.3 in /pr-checks
2026-11-03 15:49:12 +00:00
github-actions[bot]
d0468de4ad Rebuild 2026-11-03 15:38:38 +00:00
Michael B. Gale
6a39e2e9cd Merge branch 'main' into dependabot/npm_and_yarn/pr-checks/glob-14.0.3 2026-11-03 15:36:40 +00:00
Michael B. Gale
7c5ee8eaaf Merge branch 'main' into dependabot/npm_and_yarn/node-forge-1.4.1 2026-11-03 15:33:20 +00:00
Michael B. Gale
1f8cacc390 Merge pull request #4292 from github/mbg/ci/fix-sync-back
Maintain action versions by workflow in `sync-back.ts`
2026-11-03 14:27:13 +00:00
Michael B. Gale
8a05ce6067 Update JSDoc for scanGeneratedWorkflows 2026-11-03 13:41:11 +00:00
Michael B. Gale
de3ece651e Merge branch 'main' into mbg/ci/fix-sync-back 2026-11-03 12:58:27 +00:00
Michael B. Gale
cc88e02cc1 Update version of actions/download-artifact in unsupported-macos for consistency 2026-11-03 12:34:09 +00:00
Michael B. Gale
7b8e4ced67 Maintain action versions by workflow in sync-back.ts
This avoids failures on PRs where `sync-back.ts` is run as part of the "Rebuild" job if there are already version inconsistencies on the base branch.
2026-11-03 12:34:09 +00:00
Henry Mercer
093c0af4c3 Merge pull request #4290 from github/mergeback/v4.39.2-to-main-1fc58d04
Mergeback v4.39.2 refs/heads/releases/v4 into main
2026-11-03 11:09:56 +00:00
github-actions[bot]
30626207b6 Rebuild 2026-11-03 10:46:49 +00:00
github-actions[bot]
eb1e5bd7ab Update changelog and version after v4.39.2 2026-11-03 10:46:39 +00:00
dependabot[bot]
dc4b73f464 Bump node-forge from 1.4.0 to 1.4.1
Bumps [node-forge](https://github.com/digitalbazaar/forge) from 1.4.0 to 1.4.1.
- [Changelog](https://github.com/digitalbazaar/forge/blob/main/CHANGELOG.md)
- [Commits](https://github.com/digitalbazaar/forge/compare/v1.4.0...v1.4.1)

---
updated-dependencies:
- dependency-name: node-forge
  dependency-version: 1.4.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-03 10:27:23 +00:00
dependabot[bot]
3b22011a97 Bump glob from 13.0.6 to 14.0.3 in /pr-checks
Bumps [glob](https://github.com/isaacs/node-glob) from 13.0.6 to 14.0.3.
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v13.0.6...v14.0.3)

---
updated-dependencies:
- dependency-name: glob
  dependency-version: 14.0.3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-03 10:27:18 +00:00
Henry Mercer
0d5ac7a9b1 Merge pull request #4285 from github/henrymercer/automated-change-notes
Migrate bundle update workflow to new changenote tooling
2026-11-03 10:13:30 +00:00
Henry Mercer
39528452cf Remove unused updateChangelog from bundle-changelog.ts
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-11-02 17:40:43 +00:00
Henry Mercer
9bc74b13fb Create a changenote for bundle updates instead of editing the changelog
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-11-02 17:40:43 +00:00
Sam Robson
b05fe69863 fix: decode SARIF location URIs in diff-informed alert filtering 2026-11-02 16:04:35 +00:00
24 changed files with 731 additions and 263 deletions

View File

@@ -16,5 +16,5 @@ inputs:
Comma separated list of query ids that should NOT be included in this SARIF file.
runs:
using: node20
using: node24
main: index.js

View File

@@ -1,6 +1,6 @@
name: Verify that the best-effort debug artifact scan completed
description: Verifies that the best-effort debug artifact scan completed successfully during tests
runs:
using: node20
using: node24
main: index.js
post: post.js

View File

@@ -114,7 +114,7 @@ jobs:
- name: Install dependencies
run: npm ci
- name: Download workflow artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: test-mode-sarif-*
path: sarif

View File

@@ -113,11 +113,12 @@ jobs:
echo "CLI_VERSION=$cli_version" | tee -a "$GITHUB_ENV"
echo "PR_URL=$pr_url" | tee -a "$GITHUB_ENV"
- name: Create changelog note
- name: Create changenote
run: |
npx tsx pr-checks/bundle-changelog.ts
- name: Push changelog note
- name: Push changenote
run: |
git commit -am "Add changelog note"
git add unreleased-change-notes
git commit -m "Add changenote"
git push

View File

@@ -2,120 +2,124 @@
See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs.
## 3.39.2 - 03 Nov 2026
## [UNRELEASED]
No user facing changes.
## 4.39.2 - 03 Nov 2026
- Update default CodeQL bundle version to [2.27.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.4). [#4284](https://github.com/github/codeql-action/pull/4284)
- _Upcoming breaking change_: CodeQL version 2.22.3 and earlier were discontinued on 16 October 2026 alongside GitHub Enterprise Server 3.18, and will be unsupported by the next minor release of the CodeQL Action. Added a deprecation warning for customers using these versions of CodeQL. [#4266](https://github.com/github/codeql-action/pull/4266)
- Starting with macOS 27 and Xcode 27, traced analyses are unsupported. See [this blog post for more information](https://github.blog/changelog/2026-10-19-codeql-changes-for-macos-27-xcode-27-and-swift-6-4/). The CodeQL Action will now try to identify if a workflow is about to perform a traced analysis on version 27 or above of macOS or Xcode. If so, the CodeQL Action will emit a corresponding warning that will also be visible on the [Tool Status Page](https://docs.github.com/en/code-security/how-tos/find-and-fix-code-vulnerabilities/manage-your-configuration/use-the-tools-status-page-for-code-scanning). This check will be rolled out following this release of the CodeQL Action. [#4221](https://github.com/github/codeql-action/pull/4221)
- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable has been removed, as announced in the release notes for CodeQL Action 4.35.2. The `analyze` Action now warns if this environment variable is set. If you used TRAP cache cleanup to limit Actions cache usage, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#4243](https://github.com/github/codeql-action/pull/4243)
## 3.39.1 - 21 Oct 2026
## 4.39.1 - 21 Oct 2026
- Update default CodeQL bundle version to [2.27.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.3). [#4256](https://github.com/github/codeql-action/pull/4256)
## 3.39.0 - 15 Oct 2026
## 4.39.0 - 15 Oct 2026
- _Breaking change_: Bump the minimum required CodeQL bundle version to 2.20.7. [#4205](https://github.com/github/codeql-action/pull/4205)
- The `codeql-action/analyze` step now validates that a correct argument for the `checkout_path` input has been provided. The `checkout_path` input must be set to the path where the repository that is being analyzed is checked out at on the runner, if that path is something other than the workspace root. If the path does not point to a repository checkout or is different from the path that was used by `codeql-action/init`, then the CodeQL Action now produces a warning. [#4148](https://github.com/github/codeql-action/pull/4148)
- Resolved an issue with third-party caching implementations that prevented caches from being restored correctly. [#4206](https://github.com/github/codeql-action/pull/4206)
- The `codeql-action/start-proxy` step that is used in Code Scanning Default Setup now finds CodeQL releases using the same logic as `codeql-action/init`. This primarily benefits customers who are using GitHub instances other than `github.com` where the `codeql-action/start-proxy` step may previously have been unable to locate recent releases and ended up using outdated versions of the private registry authentication proxy as a result. [#4198](https://github.com/github/codeql-action/pull/4198)
## 3.38.3 - 08 Oct 2026
## 4.38.3 - 08 Oct 2026
- _Upcoming breaking change_: CodeQL version 2.21.2 and earlier were discontinued on 24 September 2026 alongside GitHub Enterprise Server 3.17, and will be unsupported by the next minor release of the CodeQL Action. Added a deprecation warning for customers using these versions of CodeQL. [#4188](https://github.com/github/codeql-action/pull/4188)
- Update default CodeQL bundle version to [2.27.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.2). [#4203](https://github.com/github/codeql-action/pull/4203)
- Fixed a bug where the decision of whether to use a per-language bundle did not account for custom configurations that reference queries outside of compiled CodeQL packs. This issue was caught during internal testing and did not affect any customer repositories. We will resume the roll out of per-language bundles in the coming weeks. [#4184](https://github.com/github/codeql-action/pull/4184)
## 3.38.2 - 24 Sept 2026
## 4.38.2 - 24 Sept 2026
- Update default CodeQL bundle version to [2.27.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.1). [#4160](https://github.com/github/codeql-action/pull/4160)
## 3.38.1 - 18 Sept 2026
## 4.38.1 - 18 Sept 2026
- The CodeQL Action now has experimental support for CodeQL releases for which per-language bundles are available. Per-language bundles support analysis for a single language and are therefore smaller than the combined bundles that allow analysis for all supported languages. As a result, per-language bundles take up less space on disk and are faster to download. We expect to roll this change out to everyone in the coming weeks. [#4146](https://github.com/github/codeql-action/pull/4146)
## 3.38.0 - 09 Sept 2026
## 4.38.0 - 09 Sept 2026
- On GitHub-hosted runners, the CodeQL Action now deletes unused CodeQL bundles from the toolcache before downloading a different bundle, which frees up disk space for the analysis. We expect to roll this change out to everyone in September. [#4124](https://github.com/github/codeql-action/pull/4124)
- The CodeQL Action now supports CodeQL releases that are compatible with Linux Arm64 and downloads the native `linux-arm64` CodeQL bundle when available. [#4072](https://github.com/github/codeql-action/pull/4072)
- Update default CodeQL bundle version to [2.27.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.27.0). [#4129](https://github.com/github/codeql-action/pull/4129)
## 3.37.9 - 26 Aug 2026
## 4.37.9 - 26 Aug 2026
- Update default CodeQL bundle version to [2.26.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.4). [#4106](https://github.com/github/codeql-action/pull/4106)
## 3.37.8 - 21 Aug 2026
## 4.37.8 - 21 Aug 2026
No user facing changes.
## 3.37.7 - 13 Aug 2026
## 4.37.7 - 13 Aug 2026
- Update default CodeQL bundle version to [2.26.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.3). [#4085](https://github.com/github/codeql-action/pull/4085)
## 3.37.6 - 04 Aug 2026
## 4.37.6 - 04 Aug 2026
- Changed the default filepath for the new remote file address format that was introduced in CodeQL Action 4.37.0 / 3.37.0 to `.github/codeql-config.yml` to align it with the suggested path that is used elsewhere. [#4070](https://github.com/github/codeql-action/pull/4070)
## 3.37.5 - 03 Aug 2026
## 4.37.5 - 03 Aug 2026
- Fixed a bug where a network error while streaming the download of the CodeQL bundle could terminate the `init` Action instead of falling back to downloading the bundle before extracting it. [#4061](https://github.com/github/codeql-action/pull/4061)
## 3.37.4 - 29 Jul 2026
## 4.37.4 - 29 Jul 2026
- This version of the CodeQL Action adds support for the `tools` input for the `codeql-action/init` step to be specified using a `github-codeql-tools` [repository property](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization). This feature will gradually be rolled out following the release of this version. Once rolled out, this allows for the CodeQL CLI version that is used in GitHub-managed workflows, such as Default Setup, to be set to a custom value. For example, customers who run into issues with rate limits when a new CodeQL CLI version is released can set the value to `toolcache` to always use the CodeQL CLI version that is available in the runner toolcache. For Advanced Setup workflows, the value provided for `tools` in the workflow definition always takes precedence unless the value of the repository property starts with `!`. [#4037](https://github.com/github/codeql-action/pull/4037)
- Update default CodeQL bundle version to [2.26.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.2). [#4051](https://github.com/github/codeql-action/pull/4051)
## 3.37.3 - 22 Jul 2026
## 4.37.3 - 22 Jul 2026
No user facing changes.
## 3.37.2 - 21 Jul 2026
## 4.37.2 - 21 Jul 2026
- The new address format for the `config-file` input that was introduced in CodeQL Action 4.37.0 is now enabled by default. In addition to the format described there, the `remote=` prefix can now be used to explicitly indicate that the input refers to a remote file. All previous input formats continue to be accepted as well. [#4023](https://github.com/github/codeql-action/pull/4023)
- The CodeQL Action can now make use of [configured private registries](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries) in Default Setup to retrieve CodeQL configuration files from remote repositories that require authentication. This will allow customers to store their CodeQL configuration in a single repository that can then be referenced by Default Setup workflows in other repositories. We expect to roll this and other, related changes out to everyone in July. [#4007](https://github.com/github/codeql-action/pull/4007)
## 3.37.1 - 16 Jul 2026
## 4.37.1 - 16 Jul 2026
- _Upcoming breaking change_: Add a deprecation warning for customers using CodeQL version 2.20.6 and earlier. These versions of CodeQL were discontinued on 1 July 2026 alongside GitHub Enterprise Server 3.16, and will be unsupported by the next minor release of the CodeQL Action. [#3956](https://github.com/github/codeql-action/pull/3956)
- Update default CodeQL bundle version to [2.26.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.1). [#4019](https://github.com/github/codeql-action/pull/4019)
## 3.37.0 - 08 Jul 2026
## 4.37.0 - 08 Jul 2026
- Update default CodeQL bundle version to [2.26.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.0). [#3995](https://github.com/github/codeql-action/pull/3995)
- In addition to the existing input format, the `config-file` input for the `codeql-action/init` step will soon support a new `[owner/]repo[@ref][:path]` format. All components except the repository name are optional. If omitted, `owner` defaults to the same owner as the repository the analysis is running for, `ref` to `main`, and `path` to `.github/codeql-action.yaml`. Support for this format ships in this version of the CodeQL Action, but will only be enabled over the coming weeks. [#3973](https://github.com/github/codeql-action/pull/3973)
## 3.36.3 - 01 Jul 2026
## 4.36.3 - 01 Jul 2026
No user facing changes.
## 3.36.2 - 04 Jun 2026
## 4.36.2 - 04 Jun 2026
- Cache CodeQL CLI version information across Actions steps. [#3943](https://github.com/github/codeql-action/pull/3943)
- Reduce requests while waiting for analysis processing by using exponential backoff when polling SARIF processing status. [#3937](https://github.com/github/codeql-action/pull/3937)
- Update default CodeQL bundle version to [2.25.6](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.6). [#3948](https://github.com/github/codeql-action/pull/3948)
## 3.36.1 - 02 Jun 2026
## 4.36.1 - 02 Jun 2026
No user facing changes.
## 3.36.0 - 22 May 2026
## 4.36.0 - 22 May 2026
- _Breaking change_: Bump the minimum required CodeQL bundle version to 2.19.4. [#3894](https://github.com/github/codeql-action/pull/3894)
- Add support for SHA-256 Git object IDs. [#3893](https://github.com/github/codeql-action/pull/3893)
- Update default CodeQL bundle version to [2.25.5](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.5). [#3926](https://github.com/github/codeql-action/pull/3926)
## 3.35.5 - 15 May 2026
## 4.35.5 - 15 May 2026
- We have improved how the JavaScript bundles for the CodeQL Action are generated to avoid duplication across bundles and reduce the size of the repository by around 70%. This should have no effect on the runtime behaviour of the CodeQL Action. [#3899](https://github.com/github/codeql-action/pull/3899)
- For performance and accuracy reasons, [improved incremental analysis](https://github.com/github/roadmap/issues/1158) will now only be enabled on a pull request when diff-informed analysis is also enabled for that run. If diff-informed analysis is unavailable (for example, because the PR diff ranges could not be computed), the action will fall back to a full analysis. [#3791](https://github.com/github/codeql-action/pull/3791)
- If multiple inputs are provided for the GitHub-internal `analysis-kinds` input, only `code-scanning` will be enabled. The `analysis-kinds` input is experimental, for GitHub-internal use only, and may change without notice at any time. [#3892](https://github.com/github/codeql-action/pull/3892)
- Added an experimental change which, when running a Code Scanning analysis for a PR with [improved incremental analysis](https://github.com/github/roadmap/issues/1158) enabled, prefers CodeQL CLI versions that have a cached overlay-base database for the configured languages. This speeds up analysis for a repository when there is not yet a cached overlay-base database for the latest CLI version. We expect to roll this change out to everyone in May. [#3880](https://github.com/github/codeql-action/pull/3880)
## 3.35.4 - 07 May 2026
## 4.35.4 - 07 May 2026
- Update default CodeQL bundle version to [2.25.4](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.4). [#3881](https://github.com/github/codeql-action/pull/3881)
## 3.35.3 - 01 May 2026
## 4.35.3 - 01 May 2026
- _Upcoming breaking change_: Add a deprecation warning for customers using CodeQL version 2.19.3 and earlier. These versions of CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise Server 3.15, and will be unsupported by the next minor release of the CodeQL Action. [#3837](https://github.com/github/codeql-action/pull/3837)
- Configurations for private registries that use Cloudsmith or GCP OIDC are now accepted. [#3850](https://github.com/github/codeql-action/pull/3850)
@@ -123,7 +127,7 @@ No user facing changes.
- Fixed a bug where two diagnostics produced within the same millisecond could overwrite each other on disk, causing one of them to be lost. [#3852](https://github.com/github/codeql-action/pull/3852)
- Update default CodeQL bundle version to [2.25.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.3). [#3865](https://github.com/github/codeql-action/pull/3865)
## 3.35.2 - 15 Apr 2026
## 4.35.2 - 15 Apr 2026
- The undocumented TRAP cache cleanup feature that could be enabled using the `CODEQL_ACTION_CLEANUP_TRAP_CACHES` environment variable is deprecated and will be removed in May 2026. If you are affected by this, we recommend disabling TRAP caching by passing the `trap-caching: false` input to the `init` Action. [#3795](https://github.com/github/codeql-action/pull/3795)
- The Git version 2.36.0 requirement for improved incremental analysis now only applies to repositories that contain submodules. [#3789](https://github.com/github/codeql-action/pull/3789)
@@ -131,26 +135,26 @@ No user facing changes.
- Fixed a bug in the validation of OIDC configurations for private registries that was added in CodeQL Action 4.33.0 / 3.33.0. [#3807](https://github.com/github/codeql-action/pull/3807)
- Update default CodeQL bundle version to [2.25.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.2). [#3823](https://github.com/github/codeql-action/pull/3823)
## 3.35.1 - 27 Mar 2026
## 4.35.1 - 27 Mar 2026
- Fix incorrect minimum required Git version for [improved incremental analysis](https://github.com/github/roadmap/issues/1158): it should have been 2.36.0, not 2.11.0. [#3781](https://github.com/github/codeql-action/pull/3781)
## 3.35.0 - 27 Mar 2026
## 4.35.0 - 27 Mar 2026
- Reduced the minimum Git version required for [improved incremental analysis](https://github.com/github/roadmap/issues/1158) from 2.38.0 to 2.11.0. [#3767](https://github.com/github/codeql-action/pull/3767)
- Update default CodeQL bundle version to [2.25.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.1). [#3773](https://github.com/github/codeql-action/pull/3773)
## 3.34.1 - 20 Mar 2026
## 4.34.1 - 20 Mar 2026
- Downgrade default CodeQL bundle version to [2.24.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.3) due to issues with a small percentage of Actions and JavaScript analyses. [#3762](https://github.com/github/codeql-action/pull/3762)
## 3.34.0 - 20 Mar 2026
## 4.34.0 - 20 Mar 2026
- Added an experimental change which disables TRAP caching when [improved incremental analysis](https://github.com/github/roadmap/issues/1158) is enabled, since improved incremental analysis supersedes TRAP caching. This will improve performance and reduce Actions cache usage. We expect to roll this change out to everyone in March. [#3569](https://github.com/github/codeql-action/pull/3569)
- We are rolling out improved incremental analysis to C/C++ analyses that use build mode `none`. We expect this rollout to be complete by the end of April 2026. [#3584](https://github.com/github/codeql-action/pull/3584)
- Update default CodeQL bundle version to [2.25.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.0). [#3585](https://github.com/github/codeql-action/pull/3585)
## 3.33.0 - 16 Mar 2026
## 4.33.0 - 16 Mar 2026
- Upcoming change: Starting April 2026, the CodeQL Action will skip collecting file coverage information on pull requests to improve analysis performance. File coverage information will still be computed on non-PR analyses. Pull request analyses will log a warning about this upcoming change. [#3562](https://github.com/github/codeql-action/pull/3562)
@@ -164,11 +168,11 @@ No user facing changes.
- Fixed the retry mechanism for database uploads. Previously this would fail with the error "Response body object should not be disturbed or locked". [#3564](https://github.com/github/codeql-action/pull/3564)
- A warning is now emitted if the CodeQL Action detects a repository property whose name suggests that it relates to the CodeQL Action, but which is not one of the properties recognised by the current version of the CodeQL Action. [#3570](https://github.com/github/codeql-action/pull/3570)
## 3.32.6 - 05 Mar 2026
## 4.32.6 - 05 Mar 2026
- Update default CodeQL bundle version to [2.24.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.3). [#3548](https://github.com/github/codeql-action/pull/3548)
## 3.32.5 - 02 Mar 2026
## 4.32.5 - 02 Mar 2026
- Repositories owned by an organization can now set up the `github-codeql-disable-overlay` custom repository property to disable [improved incremental analysis for CodeQL](https://github.com/github/roadmap/issues/1158). First, create a custom repository property with the name `github-codeql-disable-overlay` and the type "True/false" in the organization's settings. Then in the repository's settings, set this property to `true` to disable improved incremental analysis. For more information, see [Managing custom properties for repositories in your organization](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization). This feature is not yet available on GitHub Enterprise Server. [#3507](https://github.com/github/codeql-action/pull/3507)
- Added an experimental change so that when [improved incremental analysis](https://github.com/github/roadmap/issues/1158) fails on a runner — potentially due to insufficient disk space — the failure is recorded in the Actions cache so that subsequent runs will automatically skip improved incremental analysis until something changes (e.g. a larger runner is provisioned or a new CodeQL version is released). We expect to roll this change out to everyone in March. [#3487](https://github.com/github/codeql-action/pull/3487)
@@ -178,7 +182,7 @@ No user facing changes.
- Added an experimental change which allows the `start-proxy` action to resolve the CodeQL CLI version from feature flags instead of using the linked CLI bundle version. We expect to roll this change out to everyone in March. [#3512](https://github.com/github/codeql-action/pull/3512)
- The previously experimental changes from versions 4.32.3, 4.32.4, 3.32.3 and 3.32.4 are now enabled by default. [#3503](https://github.com/github/codeql-action/pull/3503), [#3504](https://github.com/github/codeql-action/pull/3504)
## 3.32.4 - 20 Feb 2026
## 4.32.4 - 20 Feb 2026
- Update default CodeQL bundle version to [2.24.2](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.2). [#3493](https://github.com/github/codeql-action/pull/3493)
- Added an experimental change which improves how certificates are generated for the authentication proxy that is used by the CodeQL Action in Default Setup when [private package registries are configured](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries). This is expected to generate more widely compatible certificates and should have no impact on analyses which are working correctly already. We expect to roll this change out to everyone in February. [#3473](https://github.com/github/codeql-action/pull/3473)
@@ -186,89 +190,89 @@ No user facing changes.
- Added a setting which allows the CodeQL Action to enable network debugging for Java programs. This will help GitHub staff support customers with troubleshooting issues in GitHub-managed CodeQL workflows, such as Default Setup. This setting can only be enabled by GitHub staff. [#3485](https://github.com/github/codeql-action/pull/3485)
- Added a setting which enables GitHub-managed workflows, such as Default Setup, to use a [nightly CodeQL CLI release](https://github.com/dsp-testing/codeql-cli-nightlies) instead of the latest, stable release that is used by default. This will help GitHub staff support customers whose analyses for a given repository or organization require early access to a change in an upcoming CodeQL CLI release. This setting can only be enabled by GitHub staff. [#3484](https://github.com/github/codeql-action/pull/3484)
## 3.32.3 - 13 Feb 2026
## 4.32.3 - 13 Feb 2026
- Added experimental support for testing connections to [private package registries](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries). This feature is not currently enabled for any analysis. In the future, it may be enabled by default for Default Setup. [#3466](https://github.com/github/codeql-action/pull/3466)
## 3.32.2 - 05 Feb 2026
## 4.32.2 - 05 Feb 2026
- Update default CodeQL bundle version to [2.24.1](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.1). [#3460](https://github.com/github/codeql-action/pull/3460)
## 3.32.1 - 02 Feb 2026
## 4.32.1 - 02 Feb 2026
- A warning is now shown in Default Setup workflow logs if a [private package registry is configured](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries) using a GitHub Personal Access Token (PAT), but no username is configured. [#3422](https://github.com/github/codeql-action/pull/3422)
- Fixed a bug which caused the CodeQL Action to fail when repository properties cannot successfully be retrieved. [#3421](https://github.com/github/codeql-action/pull/3421)
## 3.32.0 - 26 Jan 2026
## 4.32.0 - 26 Jan 2026
- Update default CodeQL bundle version to [2.24.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.0). [#3425](https://github.com/github/codeql-action/pull/3425)
## 3.31.11 - 23 Jan 2026
## 4.31.11 - 23 Jan 2026
- When running a Default Setup workflow with [Actions debugging enabled](https://docs.github.com/en/actions/how-tos/monitor-workflows/enable-debug-logging), the CodeQL Action will now use more unique names when uploading logs from the Dependabot authentication proxy as workflow artifacts. This ensures that the artifact names do not clash between multiple jobs in a build matrix. [#3409](https://github.com/github/codeql-action/pull/3409)
- Improved error handling throughout the CodeQL Action. [#3415](https://github.com/github/codeql-action/pull/3415)
- Added experimental support for automatically excluding [generated files](https://docs.github.com/en/repositories/working-with-files/managing-files/customizing-how-changed-files-appear-on-github) from the analysis. This feature is not currently enabled for any analysis. In the future, it may be enabled by default for some GitHub-managed analyses. [#3318](https://github.com/github/codeql-action/pull/3318)
- The changelog extracts that are included with releases of the CodeQL Action are now shorter to avoid duplicated information from appearing in Dependabot PRs. [#3403](https://github.com/github/codeql-action/pull/3403)
## 3.31.10 - 12 Jan 2026
## 4.31.10 - 12 Jan 2026
- Update default CodeQL bundle version to 2.23.9. [#3393](https://github.com/github/codeql-action/pull/3393)
## 3.31.9 - 16 Dec 2025
## 4.31.9 - 16 Dec 2025
No user facing changes.
## 3.31.8 - 11 Dec 2025
## 4.31.8 - 11 Dec 2025
- Update default CodeQL bundle version to 2.23.8. [#3354](https://github.com/github/codeql-action/pull/3354)
## 3.31.7 - 05 Dec 2025
## 4.31.7 - 05 Dec 2025
- Update default CodeQL bundle version to 2.23.7. [#3343](https://github.com/github/codeql-action/pull/3343)
## 3.31.6 - 01 Dec 2025
## 4.31.6 - 01 Dec 2025
No user facing changes.
## 3.31.5 - 24 Nov 2025
## 4.31.5 - 24 Nov 2025
- Update default CodeQL bundle version to 2.23.6. [#3321](https://github.com/github/codeql-action/pull/3321)
## 3.31.4 - 18 Nov 2025
## 4.31.4 - 18 Nov 2025
No user facing changes.
## 3.31.3 - 13 Nov 2025
## 4.31.3 - 13 Nov 2025
- CodeQL Action v3 will be deprecated in December 2026. The Action now logs a warning for customers who are running v3 but could be running v4. For more information, see [Upcoming deprecation of CodeQL Action v3](https://github.blog/changelog/2025-10-28-upcoming-deprecation-of-codeql-action-v3/).
- Update default CodeQL bundle version to 2.23.5. [#3288](https://github.com/github/codeql-action/pull/3288)
## 3.31.2 - 30 Oct 2025
## 4.31.2 - 30 Oct 2025
No user facing changes.
## 3.31.1 - 30 Oct 2025
## 4.31.1 - 30 Oct 2025
- The `add-snippets` input has been removed from the `analyze` action. This input has been deprecated since CodeQL Action 3.26.4 in August 2024 when this removal was announced.
## 3.31.0 - 24 Oct 2025
## 4.31.0 - 24 Oct 2025
- Bump minimum CodeQL bundle version to 2.17.6. [#3223](https://github.com/github/codeql-action/pull/3223)
- When SARIF files are uploaded by the `analyze` or `upload-sarif` actions, the CodeQL Action automatically performs post-processing steps to prepare the data for the upload. Previously, these post-processing steps were only performed before an upload took place. We are now changing this so that the post-processing steps will always be performed, even when the SARIF files are not uploaded. This does not change anything for the `upload-sarif` action. For `analyze`, this may affect Advanced Setup for CodeQL users who specify a value other than `always` for the `upload` input. [#3222](https://github.com/github/codeql-action/pull/3222)
## 3.30.9 - 17 Oct 2025
## 4.30.9 - 17 Oct 2025
- Update default CodeQL bundle version to 2.23.3. [#3205](https://github.com/github/codeql-action/pull/3205)
- Experimental: A new `setup-codeql` action has been added which is similar to `init`, except it only installs the CodeQL CLI and does not initialize a database. Do not use this in production as it is part of an internal experiment and subject to change at any time. [#3204](https://github.com/github/codeql-action/pull/3204)
## 3.30.8 - 10 Oct 2025
## 4.30.8 - 10 Oct 2025
No user facing changes.
## 3.30.7 - 06 Oct 2025
## 4.30.7 - 06 Oct 2025
- [v4+ only] The CodeQL Action now runs on Node.js v24. [#3169](https://github.com/github/codeql-action/pull/3169)
No user facing changes.
## 3.30.6 - 02 Oct 2025
- Update default CodeQL bundle version to 2.23.2. [#3168](https://github.com/github/codeql-action/pull/3168)

View File

@@ -94,6 +94,6 @@ outputs:
sarif-id:
description: The ID of the uploaded SARIF file.
runs:
using: node20
using: node24
main: "../lib/analyze-entry.js"
post: "../lib/analyze-post-entry.js"

View File

@@ -15,5 +15,5 @@ inputs:
$GITHUB_WORKSPACE as its working directory.
required: false
runs:
using: node20
using: node24
main: '../lib/autobuild-entry.js'

View File

@@ -180,6 +180,6 @@ outputs:
codeql-version:
description: The version of the CodeQL binary used for analysis
runs:
using: node20
using: node24
main: '../lib/init-entry.js'
post: '../lib/init-post-entry.js'

330
lib/entry-points.js generated
View File

@@ -157611,10 +157611,18 @@ var require_cipherModes = __commonJS({
return false;
}
var len = output.length();
if (len === 0) {
return true;
}
var count = output.at(len - 1);
if (count > this.blockSize << 2) {
if (count === 0 || count > this.blockSize || count > len) {
return false;
}
for (var i = 2; i <= count; ++i) {
if (output.at(len - i) !== count) {
return false;
}
}
output.truncate(count);
return true;
};
@@ -157676,10 +157684,18 @@ var require_cipherModes = __commonJS({
return false;
}
var len = output.length();
if (len === 0) {
return true;
}
var count = output.at(len - 1);
if (count > this.blockSize << 2) {
if (count === 0 || count > this.blockSize || count > len) {
return false;
}
for (var i = 2; i <= count; ++i) {
if (output.at(len - i) !== count) {
return false;
}
}
output.truncate(count);
return true;
};
@@ -157937,11 +157953,14 @@ var require_cipherModes = __commonJS({
} else {
additionalData = forge.util.createBuffer();
}
if ("tagLength" in options) {
this._tagLength = options.tagLength;
if (options.tagLength !== void 0 && options.tagLength !== null) {
this._tagLength = Number(options.tagLength);
} else {
this._tagLength = 128;
}
if ([128, 120, 112, 104, 96, 64, 32].indexOf(this._tagLength) === -1) {
throw new Error("Invalid tag length.");
}
this._tag = null;
if (options.decrypt) {
this._tag = forge.util.createBuffer(options.tag).getBytes();
@@ -158892,7 +158911,10 @@ var require_asn1 = __commonJS({
var subOptions = {
// enforce strict mode to avoid parsing ASN.1 from plain data
strict: true,
decodeBitStrings: true
// only decode one level of BIT STRINGs, nested decoding has
// quadratic cost due to copies for change detection
decodeBitStrings: false,
maxDepth: options.maxDepth
};
var composed = _fromDer(bytes, remaining, depth + 1, subOptions);
var used = start - bytes.length();
@@ -158996,12 +159018,16 @@ var require_asn1 = __commonJS({
asn1.oidToDer = function(oid) {
var values = oid.split(".");
var bytes = forge.util.createBuffer();
bytes.putByte(40 * parseInt(values[0], 10) + parseInt(values[1], 10));
var first = parseInt(values[0], 10);
var second = parseInt(values[1], 10);
if (!(first >= 0 && first <= 2 && second >= 0) || first < 2 && second > 39) {
throw new Error("Invalid OID; the first two arcs are out of range.");
}
var last, valueBytes, value, b;
for (var i = 2; i < values.length; ++i) {
for (var i = 1; i < values.length; ++i) {
last = true;
valueBytes = [];
value = parseInt(values[i], 10);
value = i === 1 ? 40 * first + second : parseInt(values[i], 10);
if (value > 4294967295) {
throw new Error("OID value too large; max is 32-bits.");
}
@@ -159025,9 +159051,9 @@ var require_asn1 = __commonJS({
if (typeof bytes === "string") {
bytes = forge.util.createBuffer(bytes);
}
var b = bytes.getByte();
oid = Math.floor(b / 40) + "." + b % 40;
var b;
var value = 0;
var first = true;
while (bytes.length() > 0) {
if (value > 70368744177663) {
throw new Error("OID value too large; max is 53-bits.");
@@ -159037,7 +159063,13 @@ var require_asn1 = __commonJS({
if (b & 128) {
value += b & 127;
} else {
oid += "." + (value + b);
value += b;
if (first) {
oid = value < 80 ? Math.floor(value / 40) + "." + value % 40 : "2." + (value - 80);
first = false;
} else {
oid += "." + value;
}
value = 0;
}
}
@@ -159873,12 +159905,12 @@ var require_pem = __commonJS({
};
pem.decode = function(str) {
var rval = [];
var rMessage = /\s*-----BEGIN ([A-Z0-9- ]+)-----\r?\n?([\x21-\x7e\s]+?(?:\r?\n\r?\n))?([:A-Za-z0-9+\/=\s]+?)-----END \1-----/g;
var rHeader = /([\x21-\x7e]+):\s*([\x21-\x7e\s^:]+)/;
var messages = _pemMessageScanner(str);
var rHeader = /(?:^|[^\x21-\x7e])([\x21-\x7e]+):\s*([\x21-\x7e\s^:]+)/;
var rCRLF = /\r?\n/;
var match2;
while (true) {
match2 = rMessage.exec(str);
match2 = messages.next();
if (!match2) {
break;
}
@@ -159901,7 +159933,7 @@ var require_pem = __commonJS({
var lines = match2[2].split(rCRLF);
var li = 0;
while (match2 && li < lines.length) {
var line = lines[li].replace(/\s+$/, "");
var line = rtrim(lines[li]);
for (var nl = li + 1; nl < lines.length; ++nl) {
var next = lines[nl];
if (!/\s/.test(next[0])) {
@@ -159979,6 +160011,140 @@ var require_pem = __commonJS({
function ltrim(str) {
return str.replace(/^\s+/, "");
}
function rtrim(str) {
var end = str.length;
while (end > 0 && /\s/.test(str.charAt(end - 1))) {
--end;
}
return str.substring(0, end);
}
function _pemMessageScanner(str) {
var rBody = /[:A-Za-z0-9+\/=\s]/;
var rNotBody = /[^:A-Za-z0-9+\/=\s]/g;
var rNotHeader = /[^\x21-\x7e\s]/g;
var rLabel = /[A-Z0-9- ]/;
function indexOfRegex(regex, i) {
regex.lastIndex = i;
var match2 = regex.exec(str);
return match2 ? match2.index : str.length;
}
function labelAt(i) {
for (var j = i; j < str.length && rLabel.test(str.charAt(j)); ++j) {
if (j > i && str.substr(j, 5) === "-----") {
return str.substring(i, j);
}
}
return null;
}
function blankLineEnd(i) {
if (str.charAt(i) === "\r") {
++i;
}
if (str.charAt(i) !== "\n") {
return -1;
}
if (str.charAt(++i) === "\r") {
++i;
}
return str.charAt(i) === "\n" ? i + 1 : -1;
}
function firstBlankLine(start2, end2) {
for (var i = start2; i < end2; ++i) {
var v = blankLineEnd(i);
if (v !== -1 && v < end2) {
return i;
}
}
return -1;
}
var ends = {};
for (var end = str.indexOf("-----END "); end !== -1; end = str.indexOf("-----END ", end + 1)) {
var endLabel = labelAt(end + 9);
var start = end;
while (start > 0 && rBody.test(str.charAt(start - 1))) {
--start;
}
var blank = firstBlankLine(start, end);
if (endLabel !== null && blank !== -1) {
var key = "$" + endLabel;
(ends[key] = ends[key] || []).push({ end, blank });
}
}
var pos = 0;
var headerEnd = -1;
return {
next: function() {
var begin;
while ((begin = str.indexOf("-----BEGIN ", pos)) !== -1) {
pos = begin + 1;
var label = labelAt(begin + 11);
if (label === null) {
continue;
}
var q = begin + 16 + label.length;
var bodyEnd = indexOfRegex(rNotBody, q);
var bodyEndOk = str.substr(bodyEnd, 9) === "-----END " && labelAt(bodyEnd + 9) === label;
if (q > headerEnd) {
headerEnd = indexOfRegex(rNotHeader, q);
}
var later = null;
var list = ends["$" + label];
if (list) {
var lo = 0;
var hi = list.length;
while (lo < hi) {
var mid = lo + hi >> 1;
if (list[mid].end > bodyEnd) {
hi = mid;
} else {
lo = mid + 1;
}
}
later = list[lo] || null;
}
var starts = [];
if (str.charAt(q) === "\r") {
if (str.charAt(q + 1) === "\n") {
starts.push(q + 2);
}
starts.push(q + 1);
} else if (str.charAt(q) === "\n") {
starts.push(q + 1);
}
starts.push(q);
for (var i = 0; i < starts.length; ++i) {
var t = starts[i];
var blank2 = bodyEndOk ? firstBlankLine(t + 1, bodyEnd) : -1;
var end2 = bodyEnd;
if (blank2 === -1 && later) {
blank2 = later.blank;
end2 = later.end;
}
if (blank2 !== -1 && blank2 <= headerEnd) {
var v = blankLineEnd(blank2);
pos = end2 + 14 + label.length;
return [
str.substring(begin, pos),
label,
str.substring(t, v),
str.substring(v, end2)
];
}
if (bodyEndOk && t < bodyEnd) {
pos = bodyEnd + 14 + label.length;
return [
str.substring(begin, pos),
label,
void 0,
str.substring(t, bodyEnd)
];
}
}
}
return null;
}
};
}
}
});
@@ -162416,7 +162582,7 @@ var require_jsbn = __commonJS({
return r;
}
function bnModInverse(m) {
if (this.signum() == 0) {
if (this.signum() <= 0 || m.signum() <= 0) {
return BigInteger.ZERO;
}
var ac = m.isEven();
@@ -163295,6 +163461,41 @@ var require_rsa = __commonJS({
capture: "digest"
}]
};
var _encodeDigestInfo = function(oid, digest, withParameters) {
var digestAlgorithm = [asn1.create(
asn1.Class.UNIVERSAL,
asn1.Type.OID,
false,
asn1.oidToDer(oid).getBytes()
)];
if (withParameters) {
digestAlgorithm.push(asn1.create(
asn1.Class.UNIVERSAL,
asn1.Type.NULL,
false,
""
));
}
return asn1.toDer(asn1.create(
asn1.Class.UNIVERSAL,
asn1.Type.SEQUENCE,
true,
[
asn1.create(
asn1.Class.UNIVERSAL,
asn1.Type.SEQUENCE,
true,
digestAlgorithm
),
asn1.create(
asn1.Class.UNIVERSAL,
asn1.Type.OCTETSTRING,
false,
digest
)
]
)).getBytes();
};
var emsaPkcs1v15encode = function(md2) {
var oid;
if (md2.algorithm in pki2.oids) {
@@ -163798,6 +163999,13 @@ var require_rsa = __commonJS({
);
}
}
var withParameters = _encodeDigestInfo(oid, capture.digest, true);
var withoutParameters = _encodeDigestInfo(oid, capture.digest, false);
if (d2.substring(0, withParameters.length) !== withParameters && d2.substring(0, withoutParameters.length) !== withoutParameters) {
throw new Error(
"ASN.1 object does not contain a valid RSASSA-PKCS1-v1_5 DigestInfo value."
);
}
return digest2 === capture.digest;
}
};
@@ -164758,6 +164966,9 @@ var require_pbe = __commonJS({
};
pki2.pbe.generatePkcs12Key = function(password, salt, id, iter, n, md2) {
var j, l;
if (!(iter >= 1)) {
throw new Error("PKCS#12 key derivation iteration count must be >= 1.");
}
if (typeof md2 === "undefined" || md2 === null) {
if (!("sha1" in forge.md)) {
throw new Error('"sha1" hash algorithm unavailable.');
@@ -166043,6 +166254,7 @@ var require_x509 = __commonJS({
};
var _verifySignature = function(options) {
var cert = options.certificate;
var publicKey = options.publicKey || cert.publicKey;
var scheme;
switch (cert.signatureOid) {
case oids.sha1WithRSAEncryption:
@@ -166080,7 +166292,7 @@ var require_x509 = __commonJS({
);
break;
}
return cert.publicKey.verify(
return publicKey.verify(
options.md.digest().getBytes(),
options.signature,
scheme
@@ -166300,7 +166512,8 @@ var require_x509 = __commonJS({
}
if (md2 !== null) {
rval = _verifySignature({
certificate: cert,
certificate: child,
publicKey: cert.publicKey,
md: md2,
signature: child.signature
});
@@ -167535,10 +167748,7 @@ var require_x509 = __commonJS({
}
}
if (parent) {
var parents = parent;
if (!forge.util.isArray(parents)) {
parents = [parents];
}
var parents = forge.util.isArray(parent) ? parent.slice() : [parent];
var verified = false;
while (!verified && parents.length > 0) {
parent = parents.shift();
@@ -167583,7 +167793,7 @@ var require_x509 = __commonJS({
}
}
if (error3 === null && (!first || chain.length === 0 && (!parent || selfSigned))) {
var bcExt = cert.getExtension("basicConstraints");
var bcExt = cert.getExtension({ id: "2.5.29.19" });
var keyUsageExt = cert.getExtension("keyUsage");
if (keyUsageExt !== null) {
if (!keyUsageExt.keyCertSign || bcExt === null) {
@@ -167605,7 +167815,7 @@ var require_x509 = __commonJS({
error: pki2.certificateError.bad_certificate
};
}
if (error3 === null && keyUsageExt !== null && "pathLenConstraint" in bcExt) {
if (error3 === null && bcExt !== null && "pathLenConstraint" in bcExt) {
var pathLen = depth - 1;
if (pathLen > bcExt.pathLenConstraint) {
error3 = {
@@ -167989,6 +168199,9 @@ var require_pkcs12 = __commonJS({
}
var macSalt = new forge.util.ByteBuffer(capture.macSalt);
var macIterations = "macIterations" in capture ? parseInt(forge.util.bytesToHex(capture.macIterations), 16) : 1;
if (!(macIterations >= 1)) {
throw new Error("PKCS#12 MAC iteration count must be >= 1.");
}
var macKey = p12.generateKey(
password,
macSalt,
@@ -169250,7 +169463,7 @@ var require_tls = __commonJS({
}
});
}
if (c.serverCertificate === null) {
if (c.session.serverCertificate === null) {
var error3 = {
message: "No server certificate provided. Not enough security.",
send: true,
@@ -169274,8 +169487,8 @@ var require_tls = __commonJS({
error3.alert.description = ret;
}
}
return c.error(c, error3);
}
return c.error(c, error3);
}
if (c.session.certificateRequest !== null) {
record = tls.createRecord(c, {
@@ -169531,7 +169744,7 @@ var require_tls = __commonJS({
var length = b.getInt16();
var payload = b.getBytes(length);
if (type === tls.HeartbeatMessageType.heartbeat_request) {
if (c.handshaking || length > payload.length) {
if (c.handshakes === 0 || c.handshaking || length > payload.length) {
return c.process();
}
tls.queue(c, tls.createRecord(c, {
@@ -170446,6 +170659,7 @@ var require_tls = __commonJS({
description: tls.Alert.Description.unexpected_message
}
});
return rval;
}
}
c2.record.ready = true;
@@ -170510,24 +170724,48 @@ var require_tls = __commonJS({
tls.flush(c);
}
};
var _processing = false;
var _processNext = false;
var _processRecord = function(c2) {
var rval = 0;
if (!c2.fail) {
if (c2.record !== null && c2.record.ready && c2.record.fragment.isEmpty()) {
c2.record = null;
}
if (c2.record === null) {
rval = _readRecordHeader(c2);
}
if (!c2.fail && c2.record !== null && !c2.record.ready) {
rval = _readRecord(c2);
}
if (!c2.fail && c2.record !== null && c2.record.ready) {
_update(c2, c2.record);
}
}
return rval;
};
c.process = function(data) {
var rval = 0;
if (data) {
c.input.putBytes(data);
}
if (!c.fail) {
if (c.record !== null && c.record.ready && c.record.fragment.isEmpty()) {
c.record = null;
}
if (c.record === null) {
rval = _readRecordHeader(c);
}
if (!c.fail && c.record !== null && !c.record.ready) {
rval = _readRecord(c);
}
if (!c.fail && c.record !== null && c.record.ready) {
_update(c, c.record);
if (_processing && typeof data === "undefined") {
_processNext = true;
return rval;
}
var processing = _processing;
var processNext = _processNext;
_processing = true;
_processNext = false;
try {
rval = _processRecord(c);
while (_processNext) {
_processNext = false;
_processRecord(c);
}
} finally {
_processing = processing;
_processNext = processNext;
}
return rval;
};
@@ -177993,7 +178231,7 @@ function getDiffRangesJsonFilePath(env = getEnv()) {
return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME);
}
function getActionVersion() {
return "3.39.2";
return "4.39.3";
}
function getWorkflowEventName(env = getEnv()) {
return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */);
@@ -188538,11 +188776,19 @@ function filterAlertsByDiffRange(logger2, sarifLog) {
return locations.some((physicalLocation) => {
const locationUri = physicalLocation?.artifactLocation?.uri;
const locationStartLine = physicalLocation?.region?.startLine;
if (!locationUri || locationStartLine === void 0) {
if (typeof locationUri !== "string" || !locationUri || locationStartLine === void 0) {
return false;
}
let decodedLocationUri = locationUri;
try {
decodedLocationUri = decodeURIComponent(locationUri);
} catch {
logger2.debug(
`Failed to decode location URI "${locationUri}", comparing it as a raw path`
);
}
return diffRanges.some(
(range2) => range2.path === locationUri && (range2.startLine <= locationStartLine && range2.endLine >= locationStartLine || range2.startLine === 0 && range2.endLine === 0)
(range2) => (range2.path === decodedLocationUri || range2.path === locationUri) && (range2.startLine <= locationStartLine && range2.endLine >= locationStartLine || range2.startLine === 0 && range2.endLine === 0)
);
});
});

12
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "codeql",
"version": "4.39.2",
"version": "4.39.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "codeql",
"version": "4.39.2",
"version": "4.39.3",
"license": "MIT",
"workspaces": [
"pr-checks"
@@ -33,7 +33,7 @@
"js-yaml": "^5.5.0",
"jsonschema": "1.5.0",
"long": "^5.3.2",
"node-forge": "^1.4.0",
"node-forge": "^1.4.1",
"semver": "^7.8.5",
"undici": "^7.30.1",
"uuid": "^14.0.3"
@@ -8198,9 +8198,9 @@
}
},
"node_modules/node-forge": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz",
"integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==",
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.1.tgz",
"integrity": "sha512-w5/MfWaeMrpR/5ba6fZyAUTLSuE6aYz7H/3cYrqwZEmf5eQS3IaaLgJt4MBv7HglGFWmV22K8h4U18RJQmw/ow==",
"license": "(BSD-3-Clause OR GPL-2.0)",
"engines": {
"node": ">= 6.13.0"

View File

@@ -1,6 +1,6 @@
{
"name": "codeql",
"version": "3.39.2",
"version": "4.39.3",
"private": true,
"description": "CodeQL action",
"scripts": {
@@ -42,7 +42,7 @@
"js-yaml": "^5.5.0",
"jsonschema": "1.5.0",
"long": "^5.3.2",
"node-forge": "^1.4.0",
"node-forge": "^1.4.1",
"semver": "^7.8.5",
"undici": "^7.30.1",
"uuid": "^14.0.3"

View File

@@ -10,17 +10,13 @@ import { afterEach, beforeEach, describe, it } from "node:test";
import {
CLI_VERSION_ENV_VAR,
getChangenote,
getCLIVersion,
getPRNumber,
getPRUrl,
PR_URL_ENV_VAR,
updateChangelog,
} from "./bundle-changelog";
import {
EMPTY_CHANGELOG,
NO_CHANGES_STR,
UNRELEASED_PLACEHOLDER,
} from "./changelog";
import { isValidChangenoteContent } from "./changelog/validate";
let testDir: string;
@@ -85,58 +81,15 @@ describe("getPRNumber", async () => {
});
});
const testChangelog = `${EMPTY_CHANGELOG.trimEnd()}
## 4.23.7
- Other change
## 4.23.6
${NO_CHANGES_STR}`;
const expectedChangelog = `# CodeQL Action Changelog
## ${UNRELEASED_PLACEHOLDER}
- Update default CodeQL bundle version to
## 4.23.7
- Other change
## 4.23.6
${NO_CHANGES_STR}`;
describe("updateChangelog", async () => {
await it("removes `NO_CHANGES_STR` if present in [UNRELEASED] section", async () => {
const result = updateChangelog(EMPTY_CHANGELOG, "");
assert.ok(!result.includes(NO_CHANGES_STR));
});
await it("doesn't remove `NO_CHANGES_STR` if present in versioned section", async () => {
const result = updateChangelog(
EMPTY_CHANGELOG.replace(UNRELEASED_PLACEHOLDER, "1.2.3"),
"",
describe("getChangenote", async () => {
await it("returns a note linking to the bundle release and the PR", async () => {
assert.equal(
getChangenote("1.2.3", testPrUrl),
"- Update default CodeQL bundle version to [1.2.3](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v1.2.3). [#42](https://github.com/github/codeql-action/pulls/42)\n",
);
assert.ok(result.includes(NO_CHANGES_STR));
});
await it("throws if there are no sections", async () => {
assert.throws(() => {
updateChangelog(
"# CodeQL Action Changelog",
"- Update default CodeQL bundle version to",
);
});
});
await it("adds note at the end of the first section", async () => {
const result = updateChangelog(
testChangelog,
"- Update default CodeQL bundle version to",
);
assert.deepEqual(result, expectedChangelog);
await it("returns valid changenote content", async () => {
assert.ok(isValidChangenoteContent(getChangenote("1.2.3", testPrUrl)));
});
});

View File

@@ -1,17 +1,13 @@
#!/usr/bin/env npx tsx
/**
* Updates the changelog with a change note for an updated CodeQL CLI bundle.
* Creates a changenote file for an update to the default CodeQL CLI bundle.
*/
import * as fs from "node:fs";
import * as path from "node:path";
import {
parseChangelog,
renderChangelog,
UNRELEASED_PLACEHOLDER,
} from "./changelog";
import { CHANGELOG_FILE, CLI_BUNDLE_RELEASE_URL_PREFIX } from "./config";
import { CHANGENOTES_DIR, CLI_BUNDLE_RELEASE_URL_PREFIX } from "./config";
import { getErrorMessage } from "./util";
export const CLI_VERSION_ENV_VAR = "CLI_VERSION";
@@ -58,42 +54,19 @@ export function getPRNumber(prUrl: string) {
}
/**
* Updates `changelog` by adding `changelogNote` to the first section.
* Returns the contents of the changenote file for an update to the default
* CodeQL CLI bundle.
*
* @param contents The existing changelog contents.
* @param changelogNote The note to add to the first section.
* @param cliVersion The CodeQL CLI version of the new default bundle.
* @param prUrl The URL of the PR that updates the default bundle.
* @throws If the PR number can't be determined from `prUrl`.
*/
export function updateChangelog(contents: string, changelogNote: string) {
// If the "[UNRELEASED]" section starts with "no user facing changes", remove that line.
contents = contents.replace(
`## ${UNRELEASED_PLACEHOLDER}\n\nNo user facing changes.`,
`## ${UNRELEASED_PLACEHOLDER}\n`,
);
export function getChangenote(cliVersion: string, prUrl: string): string {
// The GitHub Release for the new bundle version.
const bundleReleaseUrl = `${CLI_BUNDLE_RELEASE_URL_PREFIX}${cliVersion}`;
const changelog = parseChangelog(contents);
if (changelog.sections.length === 0) {
throw new Error("The changelog contains no existing sections.");
}
// Add the changelog note to the bottom of the first section.
const firstSection = changelog.sections[0];
const lastLine = firstSection.bodyLines.pop();
if (lastLine !== undefined && lastLine.trim() !== "") {
// We expect the last line to be empty. If it isn't for some reason,
// add it back.
firstSection.bodyLines.push(lastLine);
}
firstSection.bodyLines.push(changelogNote);
// If the last line is empty as expected, then add it back in after the new note.
if (lastLine?.trim() === "") {
firstSection.bodyLines.push(lastLine);
}
return renderChangelog(changelog);
const prNumber = getPRNumber(prUrl);
return `- Update default CodeQL bundle version to [${cliVersion}](${bundleReleaseUrl}). [#${prNumber}](${prUrl})\n`;
}
function main() {
@@ -101,22 +74,19 @@ function main() {
const cliVersion = getCLIVersion();
const prUrl = getPRUrl();
// The GitHub Release for the new bundle version.
const bundleReleaseUrl = `${CLI_BUNDLE_RELEASE_URL_PREFIX}${cliVersion}`;
// Get the PR number from the PR URL.
const prNumber = getPRNumber(prUrl);
const changelogNote = `- Update default CodeQL bundle version to [${cliVersion}](${bundleReleaseUrl}). [#${prNumber}](${prUrl})`;
let changelog = fs.readFileSync(CHANGELOG_FILE, "utf-8");
changelog = updateChangelog(changelog, changelogNote);
fs.writeFileSync(CHANGELOG_FILE, changelog);
// Include the CLI version in the file name so that changenotes for
// different bundle updates don't conflict.
const changenotePath = path.join(
CHANGENOTES_DIR,
`update-bundle-${cliVersion}.md`,
);
fs.writeFileSync(changenotePath, getChangenote(cliVersion, prUrl));
return 0;
} catch (err) {
console.error(`Failed to bundle changelog: ${getErrorMessage(err)}`);
console.error(
`Failed to create changenote for bundle update: ${getErrorMessage(err)}`,
);
return -1;
}
}

View File

@@ -48,7 +48,7 @@ validationJobs:
installNode: true
steps:
- name: Download workflow artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: test-mode-sarif-*
path: sarif

View File

@@ -14,7 +14,7 @@
"@octokit/core": "^7.0.8",
"@octokit/plugin-paginate-rest": ">=16.0.0",
"@octokit/plugin-rest-endpoint-methods": "^18.0.0",
"glob": "^13.0.6",
"glob": "^14.0.3",
"lite-matter": "^0.1.2",
"mdast-util-from-markdown": "^2.1.0",
"semver": "^7.8.5",

View File

@@ -56,9 +56,18 @@ jobs:
const result = scanGeneratedWorkflows(workflowDir);
assert.equal(result["actions/checkout"], "v4");
assert.equal(result["actions/setup-node"], "v5");
assert.equal(result["actions/setup-go"], "v6");
assert.deepEqual(
result.actionVersions["actions/checkout"],
new Set(["v4"]),
);
assert.deepEqual(
result.actionVersions["actions/setup-node"],
new Set(["v5"]),
);
assert.deepEqual(
result.actionVersions["actions/setup-go"],
new Set(["v6"]),
);
});
await it("scanning workflows with version comments", () => {
@@ -78,12 +87,18 @@ jobs:
const result = scanGeneratedWorkflows(workflowDir);
assert.equal(result["actions/checkout"], "v4");
assert.equal(
result["ruby/setup-ruby"],
"44511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0",
assert.deepEqual(
result.actionVersions["actions/checkout"],
new Set(["v4"]),
);
assert.deepEqual(
result.actionVersions["ruby/setup-ruby"],
new Set(["44511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0"]),
);
assert.deepEqual(
result.actionVersions["actions/setup-python"],
new Set(["v6 # Latest Python"]),
);
assert.equal(result["actions/setup-python"], "v6 # Latest Python");
});
await it("ignores local actions", () => {
@@ -103,9 +118,15 @@ jobs:
const result = scanGeneratedWorkflows(workflowDir);
assert.equal(result["actions/checkout"], "v4");
assert.equal("./.github/actions/local-action" in result, false);
assert.equal("./another-local-action" in result, false);
assert.deepEqual(
result.actionVersions["actions/checkout"],
new Set(["v4"]),
);
assert.equal(
"./.github/actions/local-action" in result.actionVersions,
false,
);
assert.equal("./another-local-action" in result.actionVersions, false);
});
});
@@ -128,8 +149,8 @@ const steps = [
fs.writeFileSync(syncTsPath, syncTsContent);
const actionVersions = {
"actions/setup-node": "v5",
"actions/setup-go": "v6",
"actions/setup-node": new Set(["v5"]),
"actions/setup-go": new Set(["v6"]),
};
const result = updateSyncTs(syncTsPath, actionVersions);
@@ -155,7 +176,7 @@ const steps = [
fs.writeFileSync(syncTsPath, syncTsContent);
const actionVersions = {
"actions/setup-node": "v5 # Latest version",
"actions/setup-node": new Set(["v5 # Latest version"]),
};
const result = updateSyncTs(syncTsPath, actionVersions);
@@ -182,7 +203,7 @@ const steps = [
fs.writeFileSync(syncTsPath, syncTsContent);
const actionVersions = {
"actions/setup-node": "v5",
"actions/setup-node": new Set(["v5"]),
};
const result = updateSyncTs(syncTsPath, actionVersions);
@@ -206,7 +227,9 @@ const steps = [
fs.writeFileSync(syncTsPath, syncTsContent);
const actionVersions = {
"actions/setup-node": "48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0",
"actions/setup-node": new Set([
"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0",
]),
};
const result = updateSyncTs(syncTsPath, actionVersions);
@@ -244,8 +267,9 @@ steps:
"actions/checkout": "v4",
"actions/setup-node": "v5 # Latest",
};
const byWorkflow = { ["test.yml"]: actionVersions };
const result = updateTemplateFiles(checksDir, actionVersions);
const result = updateTemplateFiles(checksDir, byWorkflow);
assert.equal(result.length, 1);
assert.ok(result.includes(templatePath));
@@ -269,8 +293,9 @@ steps:
const actionVersions = {
"ruby/setup-ruby": "55511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0",
};
const byWorkflow = { ["test.yml"]: actionVersions };
const result = updateTemplateFiles(checksDir, actionVersions);
const result = updateTemplateFiles(checksDir, byWorkflow);
assert.equal(result.length, 1);
const updatedContent = fs.readFileSync(templatePath, "utf8");

View File

@@ -27,16 +27,39 @@ const CHECKS_DIR = path.join(PR_CHECKS_DIR, "checks");
const WORKFLOW_DIR = path.join(REPO_ROOT, ".github", "workflows");
const SYNC_TS_PATH = path.join(PR_CHECKS_DIR, "sync.ts");
/** Type alias for action names. */
type ActionName = string;
/** Type alias for action versions. May include a comment. */
type ActionVersion = string;
/** Mappings of {@link ActionName}s to {@link ActionVersion}s. */
type ActionVersions = Record<ActionName, ActionVersion>;
/** Mappings of workflow names to {@link ActionVersions}. */
type ActionVersionsByWorkflow = Record<string, ActionVersions>;
/** The result of {@link scanGeneratedWorkflows}. */
type ScanWorkflowResult = {
/** A mapping of {@link ActionName}s to all encountered {@link ActionVersion}s. */
actionVersions: Record<ActionName, Set<ActionVersion>>;
/** A mapping of workflow names to {@link ActionVersions}. */
actionVersionsByWorkflow: ActionVersionsByWorkflow;
};
/**
* Scan generated workflow files to extract the latest action versions.
*
* @param workflowDir - Path to .github/workflows directory
* @returns Map from action names to their latest versions (including comments)
*
* @returns A {@link ScanWorkflowResult} object containing information about the extracted action versions.
*/
export function scanGeneratedWorkflows(
workflowDir: string,
): Record<string, string> {
const actionVersions: Record<string, string> = {};
): ScanWorkflowResult {
const actionVersionsByWorkflow: ActionVersionsByWorkflow = {};
const actionVersions: Record<ActionName, Set<ActionVersion>> = {};
const generatedFiles = fs
.readdirSync(workflowDir)
@@ -46,6 +69,10 @@ export function scanGeneratedWorkflows(
for (const filePath of generatedFiles) {
const content = fs.readFileSync(filePath, "utf8");
// Get the basename of the workflow and drop the leading `__` from it.
const workflowName = path.basename(filePath).slice(2);
actionVersionsByWorkflow[workflowName] = {};
// Find all action uses in the file, including potential comments
// This pattern captures: action_name@version_with_possible_comment
const pattern = /uses:\s+([^/\s]+\/[^@\s]+)@([^@\n]+)/g;
@@ -57,13 +84,26 @@ export function scanGeneratedWorkflows(
// Only track non-local actions (those with / but not starting with ./)
if (!actionName.startsWith("./")) {
// Assume that version numbers are consistent (this should be the case on a Dependabot update PR)
actionVersions[actionName] = versionWithComment;
// Record the version of the action for this workflow.
actionVersionsByWorkflow[workflowName][actionName] = versionWithComment;
// Record this version for the action so that we can write it to `sync.ts` if needed.
// Usually we'd expect there to be exactly one version per action across all workflows,
// but sometimes these can go out-of-sync if e.g. a workflow is added in a branch and a
// Dependabot PR is merged in the meantime that changes the version of an action that is
// used in the new workflow. Different versions of the same action across different
// workflows is not fundamentally a problem, but we may need to pick one for `sync.ts`
// so we warn there if we have multiple versions of an action.
if (actionVersions[actionName] === undefined) {
actionVersions[actionName] = new Set([versionWithComment]);
} else if (!actionVersions[actionName].has(versionWithComment)) {
actionVersions[actionName].add(versionWithComment);
}
}
}
}
return actionVersions;
return { actionVersions, actionVersionsByWorkflow };
}
/**
@@ -79,7 +119,7 @@ export function scanGeneratedWorkflows(
*/
export function updateSyncTs(
syncTsPath: string,
actionVersions: Record<string, string>,
actionVersions: Record<ActionName, Set<ActionVersion>>,
): boolean {
if (!fs.existsSync(syncTsPath)) {
throw new Error(`Could not find ${syncTsPath}`);
@@ -89,9 +129,18 @@ export function updateSyncTs(
const originalContent = content;
// Update hardcoded action versions
for (const [actionName, versionWithComment] of Object.entries(
for (const [actionName, versionsWithComments] of Object.entries(
actionVersions,
)) {
// We usually expect `versionsWithComments` to contain one version. If there are multiple,
// we arbitrarily pick one and warn about it.
const versionsWithCommentsArray = Array.from(versionsWithComments);
const versionWithComment = versionsWithCommentsArray[0];
if (versionsWithComments.size > 1) {
console.warn(
`Inconsistent versions for ${actionName}. Arbitrarily picking '${versionWithComment}'. All found: ${versionsWithCommentsArray.join(", ")}`,
);
}
// Split the scanned value into the ref (e.g. a commit SHA) and the optional
// trailing version comment (e.g. `v6.0.3`).
const ref = versionWithComment.includes("#")
@@ -138,12 +187,12 @@ export function updateSyncTs(
* Update action versions in template files in pr-checks/checks/
*
* @param checksDir - Path to pr-checks/checks directory
* @param actionVersions - Map of action names to versions (may include comments)
* @param actionVersionsByWorkflow - Map of workflows to maps of action names to versions (may include comments)
* @returns List of files that were modified
*/
export function updateTemplateFiles(
checksDir: string,
actionVersions: Record<string, string>,
actionVersionsByWorkflow: ActionVersionsByWorkflow,
): string[] {
const modifiedFiles: string[] = [];
@@ -156,6 +205,16 @@ export function updateTemplateFiles(
let content = fs.readFileSync(filePath, "utf8");
const originalContent = content;
const workflowName = path.basename(filePath);
const actionVersions = actionVersionsByWorkflow[workflowName];
if (actionVersions === undefined) {
console.info(
`Found no action versions for workflow template '${filePath}'.`,
);
continue;
}
// Update action versions
for (const [actionName, versionWithComment] of Object.entries(
actionVersions,
@@ -191,12 +250,15 @@ function main(): number {
const verbose = values.verbose ?? false;
console.info("Scanning generated workflows for latest action versions...");
const actionVersions = scanGeneratedWorkflows(WORKFLOW_DIR);
const { actionVersions, actionVersionsByWorkflow } =
scanGeneratedWorkflows(WORKFLOW_DIR);
if (verbose) {
console.info("Found action versions:");
for (const [action, version] of Object.entries(actionVersions)) {
console.info(` ${action}@${version}`);
for (const [action, versions] of Object.entries(actionVersions)) {
for (const version of versions) {
console.info(` ${action}@${version}`);
}
}
}
@@ -215,7 +277,10 @@ function main(): number {
}
// Update template files
const templateModified = updateTemplateFiles(CHECKS_DIR, actionVersions);
const templateModified = updateTemplateFiles(
CHECKS_DIR,
actionVersionsByWorkflow,
);
modifiedFiles.push(...templateModified);
if (modifiedFiles.length > 0) {

View File

@@ -21,5 +21,5 @@ outputs:
environment:
description: The inferred build environment configuration.
runs:
using: node20
using: node24
main: '../lib/resolve-environment-entry.js'

View File

@@ -51,5 +51,5 @@ outputs:
codeql-version:
description: The version of the CodeQL binary that was installed.
runs:
using: node20
using: node24
main: '../lib/setup-codeql-entry.js'

View File

@@ -13,7 +13,11 @@ import * as diffUtils from "./diff-informed-analysis-utils";
import { getEnv } from "./environment";
import { Logger } from "./logging";
import * as sarif from "./sarif";
import { RecordingLogger, setupTests } from "./testing-utils";
import {
checkExpectedLogMessages,
RecordingLogger,
setupTests,
} from "./testing-utils";
import * as uploadLib from "./upload-lib";
import { UploadPayload } from "./upload-lib/types";
import { GitHubVariant, withTmpDir } from "./util";
@@ -1015,12 +1019,62 @@ for (const analysisKind of analyses.supportedAnalysisKinds) {
);
}
function createMockSarifWithResults(
results: sarif.Result[],
): Partial<sarif.Log> {
return {
version: "2.1.0",
runs: [
{
tool: {
driver: {
name: "test tool",
},
},
results,
},
],
};
}
function createMockResultWithUri(
uri: string,
startLine = 2,
relatedUri?: string,
): sarif.Result {
return {
ruleId: "test-rule",
message: { text: "test message" },
locations: [
{
physicalLocation: {
artifactLocation: { uri },
region: { startLine },
},
},
],
...(relatedUri
? {
relatedLocations: [
{
physicalLocation: {
artifactLocation: { uri: relatedUri },
region: { startLine },
},
},
],
}
: {}),
};
}
function runFilterAlertsByDiffRange(
input: Partial<sarif.Log>,
diffRanges: diffUtils.DiffThunkRange[],
logger: Logger = new RecordingLogger(),
): Partial<sarif.Log> {
sinon.stub(diffUtils, "readDiffRangesJsonFile").returns(diffRanges);
return uploadLib.filterAlertsByDiffRange(new RecordingLogger(), input);
return uploadLib.filterAlertsByDiffRange(logger, input);
}
test.serial(
@@ -1044,3 +1098,139 @@ test.serial(
t.deepEqual(actualOutput, expectedOutput);
},
);
for (const [filePath, uri] of [
["with space/board.js", "with%20space/board.js"],
["src/[id]/board.js", "src/%5Bid%5D/board.js"],
["src/file#1.js", "src/file%231.js"],
["src/100%.js", "src/100%25.js"],
["src/literal%20.js", "src/literal%2520.js"],
["src/foo:bar.js", "src/foo%3Abar.js"],
["src/caf\u00e9.js", "src/caf%C3%A9.js"],
["src/caf\u00e9.js", "src/caf%c3%a9.js"],
]) {
test.serial(
`filterAlertsByDiffRange matches percent-encoded URI ${uri}`,
(t) => {
const matchingResult = createMockResultWithUri(uri);
const nonMatchingResult = createMockResultWithUri("other.js");
const input = createMockSarifWithResults([
matchingResult,
nonMatchingResult,
]);
const actualOutput = runFilterAlertsByDiffRange(input, [
{ path: filePath, startLine: 1, endLine: 3 },
]);
t.deepEqual(actualOutput.runs?.[0].results, [matchingResult]);
},
);
}
test.serial(
"filterAlertsByDiffRange filters out percent-encoded URI when outside diff line range",
(t) => {
const outOfRangeResult = createMockResultWithUri(
"with%20space/board.js",
2,
);
const inRangeResult = createMockResultWithUri("with%20space/board.js", 15);
const input = createMockSarifWithResults([outOfRangeResult, inRangeResult]);
const actualOutput = runFilterAlertsByDiffRange(input, [
{ path: "with space/board.js", startLine: 10, endLine: 20 },
]);
t.deepEqual(actualOutput.runs?.[0].results, [inRangeResult]);
},
);
test.serial(
"filterAlertsByDiffRange filters out percent-encoded URI when path does not match",
(t) => {
const input = createMockSarifWithResults([
createMockResultWithUri("with%20space/board.js"),
]);
const actualOutput = runFilterAlertsByDiffRange(input, [
{ path: "other/board.js", startLine: 1, endLine: 3 },
]);
t.deepEqual(actualOutput.runs?.[0].results, []);
},
);
test.serial(
"filterAlertsByDiffRange keeps alert when relatedLocations has a matching percent-encoded URI",
(t) => {
const matchingRelatedResult = createMockResultWithUri(
"src/promiseUtils.js",
2,
"with%20space/ParseObject.js",
);
const nonMatchingResult = createMockResultWithUri("other.js");
const input = createMockSarifWithResults([
matchingRelatedResult,
nonMatchingResult,
]);
const actualOutput = runFilterAlertsByDiffRange(input, [
{ path: "with space/ParseObject.js", startLine: 1, endLine: 3 },
]);
t.deepEqual(actualOutput.runs?.[0].results, [matchingRelatedResult]);
},
);
for (const uri of ["dir%ZZ/board.js", "src/bad%.js", "src/bad%C3%28.js"]) {
test.serial(
`filterAlertsByDiffRange falls back to raw path for malformed URI ${uri}`,
(t) => {
const logger = new RecordingLogger();
const matchingResult = createMockResultWithUri(uri);
const input = createMockSarifWithResults([matchingResult]);
const actualOutput = runFilterAlertsByDiffRange(
input,
[{ path: uri, startLine: 1, endLine: 3 }],
logger,
);
t.deepEqual(actualOutput.runs?.[0].results, [matchingResult]);
checkExpectedLogMessages(t, logger.messages, [
`Failed to decode location URI "${uri}", comparing it as a raw path`,
]);
},
);
}
test.serial(
"filterAlertsByDiffRange filters out malformed URI when raw path does not match",
(t) => {
const logger = new RecordingLogger();
const input = createMockSarifWithResults([
createMockResultWithUri("dir%ZZ/board.js"),
]);
const actualOutput = runFilterAlertsByDiffRange(
input,
[{ path: "src/different.js", startLine: 1, endLine: 3 }],
logger,
);
t.deepEqual(actualOutput.runs?.[0].results, []);
checkExpectedLogMessages(t, logger.messages, [
'Failed to decode location URI "dir%ZZ/board.js", comparing it as a raw path',
]);
},
);
test.serial(
"filterAlertsByDiffRange matches raw unencoded path containing valid percent-encoding sequence",
(t) => {
const matchingResult = createMockResultWithUri("dir/100%20done.js");
const input = createMockSarifWithResults([matchingResult]);
const actualOutput = runFilterAlertsByDiffRange(input, [
{ path: "dir/100%20done.js", startLine: 1, endLine: 3 },
]);
t.deepEqual(actualOutput.runs?.[0].results, [matchingResult]);
},
);

View File

@@ -1099,9 +1099,21 @@ export function filterAlertsByDiffRange(
return locations.some((physicalLocation) => {
const locationUri = physicalLocation?.artifactLocation?.uri;
const locationStartLine = physicalLocation?.region?.startLine;
if (!locationUri || locationStartLine === undefined) {
if (
typeof locationUri !== "string" ||
!locationUri ||
locationStartLine === undefined
) {
return false;
}
let decodedLocationUri = locationUri;
try {
decodedLocationUri = decodeURIComponent(locationUri);
} catch {
logger.debug(
`Failed to decode location URI "${locationUri}", comparing it as a raw path`,
);
}
// Alert filtering here replicates the same behavior as the restrictAlertsTo
// extensible predicate in CodeQL. See the restrictAlertsTo documentation
// https://codeql.github.com/codeql-standard-libraries/csharp/codeql/util/AlertFiltering.qll/predicate.AlertFiltering$restrictAlertsTo.3.html
@@ -1109,7 +1121,8 @@ export function filterAlertsByDiffRange(
// of an alert location.
return diffRanges.some(
(range) =>
range.path === locationUri &&
(range.path === decodedLocationUri ||
range.path === locationUri) &&
((range.startLine <= locationStartLine &&
range.endLine >= locationStartLine) ||
(range.startLine === 0 && range.endLine === 0)),

View File

@@ -29,6 +29,6 @@ outputs:
proxy_urls:
description: A stringified JSON array of objects containing the types and URLs of the configured registries.
runs:
using: node20
using: node24
main: "../lib/start-proxy-entry.js"
post: "../lib/start-proxy-post-entry.js"

View File

@@ -0,0 +1 @@
- Fixed diff-informed alert filtering incorrectly removing alerts in changed files whose paths contain spaces, special characters, or non-ASCII characters. [#4283](https://github.com/github/codeql-action/pull/4283)

View File

@@ -41,6 +41,6 @@ outputs:
{ "code-scanning": "some-id", "code-quality": "some-other-id" }
runs:
using: node20
using: node24
main: '../lib/upload-sarif-entry.js'
post: '../lib/upload-sarif-post-entry.js'