Compiling any agentic workflow in this repo with a locally-installed gh aw extension (v0.83.1) rewrites two security-relevant action pins away from the repo-aligned values in every lock file it touches. Because the corruption lands in generated files that reviewers rarely read line-by-line, it can ride along unnoticed in an unrelated PR.
Surfaced while working on #10252, but it is not specific to that change — it affects every agentic workflow and every contributor compiling locally.
The two corruptions
1. actions/checkout downgraded v7.0.1 → v7.0.0
|
SHA |
Version |
Occurrences in committed locks |
| Aligned (expected) |
3d3c42e5aac5ba805825da76410c181273ba90b1 |
v7.0.1 |
168 |
| Emitted by local CLI |
9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 |
v7.0.0 |
0 |
The repo deliberately aligned every checkout pin to v7.0.1 in #10174. A local compile partially undoes that.
2. github/gh-aw-actions/setup un-pinned from an immutable SHA to a mutable tag
- uses: github/gh-aw-actions/setup@8bdba8075360648fe6802302a5b4e016361dc6ac # v0.83.1
+ uses: github/gh-aw-actions/setup@v0.83.1
This one is the more serious of the two: a version delta still resolves to a fixed commit, whereas a mutable tag can be repointed upstream at any time. Observed when regenerating .github/workflows/agentic_commands.yml.
Mechanism
.github/aw/actions-lock.json keys its checkout override by version string and holds only an actions/checkout@v7.0.1 entry. For framework-injected steps (patch-context, threat-detection, create-PR) the local CLI build requests checkout at v7.0.0, so the lookup key-misses, no override applies, and the CLI's stale built-in SHA wins.
Note that actions-lock.json cannot be edited to fix this — the injected version label is baked into the binary, so adding a v7.0.0 entry would only pin the downgrade rather than prevent it.
Why the compiler_version header does not catch it
Both the aligned CI toolchain and the local build stamp "compiler_version":"v0.83.1" in the gh-aw-manifest header. The header asserts an identity claim, not the emitted bytes — two builds carrying the same version string can embed different defaults for framework-injected steps. Checking the header is a reasonable first move but is not sufficient; the reliable test is to regenerate a known-good baseline and full-file-diff it.
Steps To Reproduce
# sh.exe must be on PATH on Windows, e.g.:
# $env:PATH = "C:\Program Files\Git\bin;$env:PATH"
gh aw compile add-tests --strict
git diff .github/workflows/add-tests.lock.yml
Expected behavior
Recompiling an unmodified workflow with a matching compiler version produces a byte-identical lock file, preserving both pins.
Actual behavior
Exactly 5 changed lines, all checkout SHA/version, byte-identical otherwise:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
+# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
Regenerating the router additionally un-pins github/gh-aw-actions/setup to @v0.83.1.
Additional context
- Not reproducible in CI.
agentics-maintenance.yml compiles via the pinned github/gh-aw-actions/setup@8bdba8075360648fe6802302a5b4e016361dc6ac # v0.83.1 action rather than a local build, and that path preserves both pins. Any recompile on the aligned toolchain self-heals an affected lock.
gh extension upgrade aw fails under SAML (HTTP 403) in at least one affected environment, so contributors cannot straightforwardly correct the local build in place.
- No CI gate detects it.
check-vendored-files.yml does not verify lock freshness or pin alignment, so a corrupted lock passes review with green CI.
Possible mitigations
- Add a CI check that recompiles the workflows on the pinned setup action and fails if any committed
.lock.yml differs — this catches both stale locks and corrupted pins.
- Add a narrower guard that greps generated locks for known-bad pins (any
actions/checkout SHA other than the aligned one; any unpinned uses: reference).
- Document in
.github/workflows/README.md that locks must be generated on the CI toolchain, not locally.
- Raise the version-keyed-override behaviour upstream with
gh-aw, since the key-miss silently falling back to a built-in default is what makes this invisible.
Compiling any agentic workflow in this repo with a locally-installed
gh awextension (v0.83.1) rewrites two security-relevant action pins away from the repo-aligned values in every lock file it touches. Because the corruption lands in generated files that reviewers rarely read line-by-line, it can ride along unnoticed in an unrelated PR.Surfaced while working on #10252, but it is not specific to that change — it affects every agentic workflow and every contributor compiling locally.
The two corruptions
1.
actions/checkoutdowngraded v7.0.1 → v7.0.03d3c42e5aac5ba805825da76410c181273ba90b19c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0The repo deliberately aligned every checkout pin to v7.0.1 in #10174. A local compile partially undoes that.
2.
github/gh-aw-actions/setupun-pinned from an immutable SHA to a mutable tagThis one is the more serious of the two: a version delta still resolves to a fixed commit, whereas a mutable tag can be repointed upstream at any time. Observed when regenerating
.github/workflows/agentic_commands.yml.Mechanism
.github/aw/actions-lock.jsonkeys its checkout override by version string and holds only anactions/checkout@v7.0.1entry. For framework-injected steps (patch-context, threat-detection, create-PR) the local CLI build requests checkout at v7.0.0, so the lookup key-misses, no override applies, and the CLI's stale built-in SHA wins.Note that
actions-lock.jsoncannot be edited to fix this — the injected version label is baked into the binary, so adding av7.0.0entry would only pin the downgrade rather than prevent it.Why the
compiler_versionheader does not catch itBoth the aligned CI toolchain and the local build stamp
"compiler_version":"v0.83.1"in thegh-aw-manifestheader. The header asserts an identity claim, not the emitted bytes — two builds carrying the same version string can embed different defaults for framework-injected steps. Checking the header is a reasonable first move but is not sufficient; the reliable test is to regenerate a known-good baseline and full-file-diff it.Steps To Reproduce
Expected behavior
Recompiling an unmodified workflow with a matching compiler version produces a byte-identical lock file, preserving both pins.
Actual behavior
Exactly 5 changed lines, all checkout SHA/version, byte-identical otherwise:
Regenerating the router additionally un-pins
github/gh-aw-actions/setupto@v0.83.1.Additional context
agentics-maintenance.ymlcompiles via the pinnedgithub/gh-aw-actions/setup@8bdba8075360648fe6802302a5b4e016361dc6ac # v0.83.1action rather than a local build, and that path preserves both pins. Any recompile on the aligned toolchain self-heals an affected lock.gh extension upgrade awfails under SAML (HTTP 403) in at least one affected environment, so contributors cannot straightforwardly correct the local build in place.check-vendored-files.ymldoes not verify lock freshness or pin alignment, so a corrupted lock passes review with green CI.Possible mitigations
.lock.ymldiffers — this catches both stale locks and corrupted pins.actions/checkoutSHA other than the aligned one; any unpinneduses:reference)..github/workflows/README.mdthat locks must be generated on the CI toolchain, not locally.gh-aw, since the key-miss silently falling back to a built-in default is what makes this invisible.