You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Model packs (<lang>/ext, <lang>/ext-library-sources) silently apply zero models when the consumer's CodeQL CLI doesn't bundle the exact extensionTargets version #206
Every published model/extension pack in this repo (csharp/ext, csharp/ext-library-sources, go/ext, java/ext, java/ext-library-sources, python/ext) pins extensionTargets to a single exactcodeql/<lang>-all version, e.g.:
Per the CodeQL model pack docs, a model pack's data extensions are only injected into an analysis if the codeql/<lang>-all version actually resolved for that analysis satisfies extensionTargets. I've now empirically confirmed that when it doesn't, our sink/source/summary models are silently skipped — no error, no warning that mentions the mismatch — and the analysis just quietly loses that coverage.
This affects any consumer whose CodeQL CLI doesn't happen to bundle exactly the pinned version — not just contributors testing locally.
Reproduction (100% confirmed, not just doc-reading)
Environment: local CLI 2.25.6 (bundles codeql/java-all9.1.2), repo pinned to CLI 2.26.1 (.codeqlversion), java/ext/qlpack.yml pins extensionTargets: codeql/java-all: '9.2.1'.
codeql pack install java/test (no flags, exactly what ci.yml's "Install Dependencies" step runs):
Nothing downloaded.
WARNING: Pack 'codeql/java-all' was found via '--additional-packs'. If the generated
'codeql-pack.lock.yml' file is committed to source control, other users will also have
to use '--additional-packs' when compiling or running queries.
(C:\Utils\codeql\qlpacks\codeql\java-all\9.1.2\qlpack.yml:1,1-1)
...
Nothing to install.
The CLI does not attempt to fetch the pinned 9.2.1 from the registry — it silently substitutes its own bundled 9.1.2 via the implicit "found via --additional-packs" path, with only a generic reproducibility warning (nothing that says "this doesn't satisfy the pinned version").
codeql test run java/test/security/CWE-089/spring-r2dbc --failing-exitcode=122 --verbosity=progress --ram=2048 --format=json (the exact command ci.yml's "Test Queries" step runs) — the DatabaseClientSqlInjection.ql test (added in Java: model Spring R2DBC DatabaseClient and io.r2dbc.spi as SQL injection sinks #204) fails silently: 0 actual results vs. 6 expected, FAILED(RESULT), no compile error, no diagnostic about codeql/java-all or extensionTargets at all.
Isolated the fix: temporarily changed java/ext/qlpack.yml's extensionTargets from the exact pin '9.2.1' to a range, '>=9.1.0 <=9.2.1', and re-ran step 2 with the same CLI (2.25.6/java-all 9.1.2, nothing else changed) — all 6 expected results now pass. This proves:
The MaD row schema for sinkModel/summaryModel is compatible across 9.1.2–9.2.1 (no breaking schema change in that span).
A version range instead of an exact pin is a viable, low-risk fix for this specific gap.
(Reverted both experimental edits after confirming — no code changes are included in this issue.)
Root cause (two layers)
CLI dependency resolution silently prefers its own bundled codeql/<lang>-all over fetching a different pinned version from the registry, when the bundled one is found via the CLI's implicit --additional-packs-style search path — with no check that the bundled version actually satisfies the declared dependency/lock-file version, and only a generic "you'll need --additional-packs too" warning (not a version-mismatch warning). This appears to be true in both directions (older CLI + newer pin, or newer CLI + older pin) since resolution isn't semver-gated at that layer.
extensionTargets then silently fails to match whatever codeql/<lang>-all version actually got resolved (per (1)), so the model pack's dataExtensions are never injected into the analysis — with no error/warning at all from this layer either.
Net effect: any consumer of a published <lang>/ext or <lang>/ext-library-sources pack — not just local contributors — whose CodeQL CLI doesn't bundle a codeql/<lang>-all inside our pinned extensionTargets range gets zero of that pack's models applied, silently, with no signal anything went wrong.
Scope
Every language's ext/ext-library-sources pack pins an exact extensionTargets version today, all set by .github/scripts/pin-codeql-library-versions.sh on every .codeqlversion bump:
Pack
Current exact pin
csharp/ext, csharp/ext-library-sources
codeql/csharp-all: '7.1.0'
go/ext
codeql/go-all: '7.2.1'
java/ext, java/ext-library-sources
codeql/java-all: '9.2.1'
python/ext
codeql/python-all: '7.2.1'
So this isn't specific to the Spring R2DBC models (#204) — it's a systemic, repo-wide characteristic of how every model pack we publish is pinned.
What we can do today (partial, undocumented workaround)
Historical pack versions remain published on GHCR (e.g. githubsecuritylab/codeql-java-extensions has 13 tags going back ~3 years), and each version's OCI manifest carries a com.github.codeql.cli.version annotation recording which CLI built it — so a consumer could in principle pin their own dependency to an older, compatible release matching their CLI. But: (a) nothing documents this mapping anywhere today (a user would need to inspect GHCR manifests directly), and (b) it doesn't fully solve determinism on its own, since layer (1) above can still substitute an unexpected bundled version underneath even a correctly-pinned extensions pack.
Options to consider (needs a maintainer decision, not solo-fixing this)
Broaden extensionTargets to a version range (e.g. >=X.Y.0 or a wider bound) instead of re-pinning to the exact bundle version on every CLI bump — confirmed technically viable above, but needs a decision on how wide is safe (risk: if the MaD schema ever changes within the chosen range, that's a real compile break, not just a silent skip) and whether pin-codeql-library-versions.sh's "always overwrite to exact bundle version" approach should change for extensionTargets specifically (still fine for dependencies:, which resolves/locks correctly).
Document the CLI-version ↔ pack-version compatibility mapping (e.g. a table sourced from com.github.codeql.cli.version manifest annotations) so consumers on older CLIs know which pack version to pin — doesn't fix the silent-failure mode, just makes the existing workaround discoverable.
File an upstream CodeQL CLI issue about layer (1) — packs found via the implicit bundled/--additional-packs path aren't checked against the declared dependency version at all, with only a generic (not version-specific) warning. Searched github/codeql issues; didn't find an existing report of this exact behavior.
Some combination of the above.
Flagging this for a maintainer decision rather than picking one unilaterally, per this repo's convention that CLI-compatibility trade-offs are a judgment call, not something to resolve solo.
Summary
Every published model/extension pack in this repo (
csharp/ext,csharp/ext-library-sources,go/ext,java/ext,java/ext-library-sources,python/ext) pinsextensionTargetsto a single exactcodeql/<lang>-allversion, e.g.:Per the CodeQL model pack docs, a model pack's data extensions are only injected into an analysis if the
codeql/<lang>-allversion actually resolved for that analysis satisfiesextensionTargets. I've now empirically confirmed that when it doesn't, our sink/source/summary models are silently skipped — no error, no warning that mentions the mismatch — and the analysis just quietly loses that coverage.This affects any consumer whose CodeQL CLI doesn't happen to bundle exactly the pinned version — not just contributors testing locally.
Reproduction (100% confirmed, not just doc-reading)
Environment: local CLI
2.25.6(bundlescodeql/java-all9.1.2), repo pinned to CLI2.26.1(.codeqlversion),java/ext/qlpack.ymlpinsextensionTargets: codeql/java-all: '9.2.1'.codeql pack install java/test(no flags, exactly whatci.yml's "Install Dependencies" step runs):The CLI does not attempt to fetch the pinned
9.2.1from the registry — it silently substitutes its own bundled9.1.2via the implicit "found via--additional-packs" path, with only a generic reproducibility warning (nothing that says "this doesn't satisfy the pinned version").codeql test run java/test/security/CWE-089/spring-r2dbc --failing-exitcode=122 --verbosity=progress --ram=2048 --format=json(the exact commandci.yml's "Test Queries" step runs) — theDatabaseClientSqlInjection.qltest (added in Java: model Spring R2DBCDatabaseClientandio.r2dbc.spias SQL injection sinks #204) fails silently: 0 actual results vs. 6 expected,FAILED(RESULT), no compile error, no diagnostic aboutcodeql/java-allorextensionTargetsat all.Isolated the fix: temporarily changed
java/ext/qlpack.yml'sextensionTargetsfrom the exact pin'9.2.1'to a range,'>=9.1.0 <=9.2.1', and re-ran step 2 with the same CLI (2.25.6/java-all 9.1.2, nothing else changed) — all 6 expected results now pass. This proves:sinkModel/summaryModelis compatible across9.1.2–9.2.1(no breaking schema change in that span).(Reverted both experimental edits after confirming — no code changes are included in this issue.)
Root cause (two layers)
codeql/<lang>-allover fetching a different pinned version from the registry, when the bundled one is found via the CLI's implicit--additional-packs-style search path — with no check that the bundled version actually satisfies the declared dependency/lock-file version, and only a generic "you'll need--additional-packstoo" warning (not a version-mismatch warning). This appears to be true in both directions (older CLI + newer pin, or newer CLI + older pin) since resolution isn't semver-gated at that layer.extensionTargetsthen silently fails to match whatevercodeql/<lang>-allversion actually got resolved (per (1)), so the model pack'sdataExtensionsare never injected into the analysis — with no error/warning at all from this layer either.Net effect: any consumer of a published
<lang>/extor<lang>/ext-library-sourcespack — not just local contributors — whose CodeQL CLI doesn't bundle acodeql/<lang>-allinside our pinnedextensionTargetsrange gets zero of that pack's models applied, silently, with no signal anything went wrong.Scope
Every language's
ext/ext-library-sourcespack pins an exactextensionTargetsversion today, all set by.github/scripts/pin-codeql-library-versions.shon every.codeqlversionbump:csharp/ext,csharp/ext-library-sourcescodeql/csharp-all: '7.1.0'go/extcodeql/go-all: '7.2.1'java/ext,java/ext-library-sourcescodeql/java-all: '9.2.1'python/extcodeql/python-all: '7.2.1'So this isn't specific to the Spring R2DBC models (#204) — it's a systemic, repo-wide characteristic of how every model pack we publish is pinned.
What we can do today (partial, undocumented workaround)
Historical pack versions remain published on GHCR (e.g.
githubsecuritylab/codeql-java-extensionshas 13 tags going back ~3 years), and each version's OCI manifest carries acom.github.codeql.cli.versionannotation recording which CLI built it — so a consumer could in principle pin their own dependency to an older, compatible release matching their CLI. But: (a) nothing documents this mapping anywhere today (a user would need to inspect GHCR manifests directly), and (b) it doesn't fully solve determinism on its own, since layer (1) above can still substitute an unexpected bundled version underneath even a correctly-pinned extensions pack.Options to consider (needs a maintainer decision, not solo-fixing this)
extensionTargetsto a version range (e.g.>=X.Y.0or a wider bound) instead of re-pinning to the exact bundle version on every CLI bump — confirmed technically viable above, but needs a decision on how wide is safe (risk: if the MaD schema ever changes within the chosen range, that's a real compile break, not just a silent skip) and whetherpin-codeql-library-versions.sh's "always overwrite to exact bundle version" approach should change forextensionTargetsspecifically (still fine fordependencies:, which resolves/locks correctly).com.github.codeql.cli.versionmanifest annotations) so consumers on older CLIs know which pack version to pin — doesn't fix the silent-failure mode, just makes the existing workaround discoverable.--additional-packspath aren't checked against the declared dependency version at all, with only a generic (not version-specific) warning. Searchedgithub/codeqlissues; didn't find an existing report of this exact behavior.Flagging this for a maintainer decision rather than picking one unilaterally, per this repo's convention that CLI-compatibility trade-offs are a judgment call, not something to resolve solo.