Skip to content

codeql_scan is broken for every language: init and autobuild pinned to different codeql-action releases (+2 gaps, 1 question) #633

Closed

Description

@ferr3ira-gabriel

Summary

Three independent problems found while standardising LerianStudio/severino (TypeScript) onto js-pr-validation.yml / js-release.yml / routine.yml at @v1.47.5. The first is a hard breakage that affects every language, not just TypeScript; the other two are gaps a caller cannot work around.

Each was verified against the workflow files at the tag in use and against a real run — not inferred. Where I initially believed something else was wrong, that is noted, because the wrong diagnosis is an easy one to repeat.


1. codeql_scan is broken for every language: init and autobuild are pinned to different releases

Severity: high. The job cannot succeed as configured, in any repo, for any language.

src/security/codeql-init/action.yml pins:

uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13  # v4.35.1

while .github/workflows/pr-security-scan.yml pins:

- name: Autobuild
  uses: github/codeql-action/autobuild@7188fc363630916deb702c7fdcf4e481b751f97a  # v4.37.1

autobuild then refuses the config init wrote:

##[error]We were unable to automatically build your code. Please replace the call to
the autobuild action with your custom build steps. Loaded a configuration file for
version '4.35.1', but running version '4.37.1'

Observed on severino run 30415516830, job 90461677986, with codeql_languages: javascript-typescript.

I confirmed the SHA→version mapping directly rather than trusting the comments: c10b806 is the update-v4.35.1 merge, 7188fc3 is update-v4.37.1 and is exactly what the v4.37.1 tag resolves to.

Why this has not been reported before: nothing in the org enables it. go-boilerplate-ddd — the reference repo other repos are standardised against — does not set enable_codeql, so its codeql_scan job has only ever reported skipped. Severino appears to be the first caller to switch it on.

Still present at @v1.49.0, and wider. pr-security-scan.yml bumped autobuild to e4fba86 (= update-v4.37.3) while codeql-init still pins c10b806 (= update-v4.35.1), so the gap grew from 4.35.1↔4.37.1 to 4.35.1↔4.37.3.

Worth flagging separately: at @v1.49.0 both pins carry the comment # v4 rather than a specific version. The mismatch is now invisible to anyone reading the files — the two lines look identical and are two releases apart. Whatever the fix, keeping the exact version in the comment is what makes a future drift reviewable.

Fix: pin every codeql-action step to the same release. Ideally init, autobuild and analyze should all resolve from one place so they cannot drift again — a single codeql_action_ref input, or all three moved into the codeql-init composite.

Correction to my own first diagnosis, in case it saves someone the detour: I initially recorded this as "Autobuild cannot build a TypeScript project". That was wrong, and the error message's first sentence is what makes it plausible — the real cause is the second sentence. It is a version mismatch, and it would break a Go caller identically.


2. codeql-init exposes no build-mode, and the Go-specific steps run for every language

Even with #1 fixed, a JS/TS caller cannot express what the language needs.

src/security/codeql-init/action.yml forwards only languages, queries and config-file. There is no build-mode input, so build-mode: none — the documented mode for JavaScript/TypeScript, and the one that makes autobuild unnecessary rather than merely harmless — cannot be selected by a caller.

Separately, two steps in codeql_scan run unconditionally regardless of codeql_languages:

- name: Configure private Go modules access
  run: |
    git config --global url."https://x-access-token:${TOKEN}@github.com/".insteadOf "https://github.com/"
    echo "GOPRIVATE=github.com/LerianStudio/*" >> "$GITHUB_ENV"

- name: Autobuild
  uses: github/codeql-action/autobuild@...

For a TypeScript repo the first writes a credential into the runner's global git config for no reason, and the second has nothing to do. Worth gating both on the language, and worth noting the credential is written with --global in a job triggered by pull_request.

Fix: add a build-mode input to codeql-init, and make the Go-modules step and Autobuild conditional on a compiled language being requested.


3. id-token: write is required of every caller on the pull_request path, with no consumer

js-pr-validation.yml requires callers to grant id-token: write, and callers must also use secrets: inherit. Severino does both today, because the job fails otherwise.

The concern (raised by an automated reviewer on our PR, and I think correctly): this workflow runs on pull_request, i.e. against untrusted contributor code, and I could not find a step on the PR path that consumes OIDC. If that is right, every caller is granting OIDC to a workflow that runs untrusted code and does not need it.

I want to be explicit that this one is a question, not a finding. What I checked: js-pr-validation.yml, pr-validation.yml, frontend-pr-analysis.yml and pr-security-scan.yml at @v1.47.5, plus all eleven src/** composites that pr-security-scan.yml calls. The only occurrences of id-token are the two permissions: declarations themselves; I found no aws-actions/*, google-github-actions/*, azure/login, or getIDToken call on that path. But I cannot prove a negative through this much nesting, so: if there is a consumer, documenting which step needs it would be enough. If there is not, dropping the requirement from the PR path would let callers stop granting OIDC to a workflow that runs untrusted code.

Related, and the reason we did not simply narrow it on our side: DOCKER_USERNAME / DOCKER_PASSWORD reach the nested workflows only through secrets: inherit, so enumerating secrets explicitly breaks prepare_matrix. A caller therefore cannot reduce either the OIDC grant or the secret surface without breaking the pipeline — which is what makes this an upstream question rather than a caller-side fix.


4. dependabot.yml ignores LerianStudio/*, so no shared-workflow reference is watched

.github/dependabot.yml in the consuming repos ignores the LerianStudio/* namespace, so nothing proposes updates to @vX.Y.Z references to these workflows.

Concrete consequence: severino sat on @v1.47.5 while go-boilerplate-ddd was already on @v1.49.0 — two minor versions of drift between a repo and the reference repo it was standardised against, with nothing to surface it.

An automated reviewer suggested pinning to commit SHAs instead. We declined, and I mention it because the reasoning matters for whatever this repo recommends: with the owner ignored by Dependabot, a SHA would freeze the reference permanently with nothing able to bump it, while a tag at least moves when someone bumps it and is legible enough for a reviewer to notice drift. The real fix is Dependabot coverage for the namespace, or a policy applied across every repo at once — neither of which a single caller can do.


Environment

Not reported, for the record

I had also planned to report --coverageReporters being passed to vitest as a Jest-only flag. That was wrong — frontend-pr-analysis.yml already detects the vitest major version and switches to --coverage.reporter for 3+, at @v1.47.5 and later. Mentioning it only so nobody re-opens it from our earlier notes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething is not working as expected

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions