Filed after #736 was merged past a red CodeQL cell. The merge was right and the alert is inherited rather than introduced, and that is precisely the problem worth writing down: this cell has been red for a month, it is red on every PR, and the reason it is safe to merge past is now discovered by hand each time.
What is actually open
Queried today from the code scanning API, all state open:
| count |
severity |
rule |
| 12 |
high |
actions/cache-poisoning/poisonable-step |
| 1 |
high |
actions/cache-poisoning/direct-cache |
| 1 |
high |
py/bad-tag-filter |
| 2 |
medium |
py/stack-trace-exposure |
All 13 cache poisoning alerts are in one file, .github/workflows/quality.yml, and all 13 were created on 13 or 16 August:
8 2026-08-13 quality.yml:3502 19 2026-08-16 quality.yml:3717
9 2026-08-13 quality.yml:3589 13 2026-08-13 quality.yml:5939
10 2026-08-13 quality.yml:5390 14 2026-08-13 quality.yml:6908
11 2026-08-13 quality.yml:5438 15 2026-08-13 quality.yml:6978
12 2026-08-13 quality.yml:5562 16 2026-08-13 quality.yml:7275
17 2026-08-13 quality.yml:8288 18 2026-08-13 quality.yml:8399
7 2026-08-13 quality.yml:8268 (direct-cache)
The rule is Cache Poisoning via execution of untrusted code. The shape is the familiar one: a job that runs repository code, in a context that can write the Actions cache, on a workflow that is pull_request-triggered. quality.yml is consumed by all 21 core apps, so whatever the right answer is, it is the same answer 21 times.
Why it needs an issue rather than a triage
The alerts were not suppressed and nobody has decided they are acceptable. What has happened instead is that each merge rediscovers, individually, that the red is old. For #736 the evidence was: alerts created a month before the branch existed, a branch first pushed the previous afternoon, a diff touching no workflow file at all, and a pull_request code scanning check that reports the alerts present in the merge commit rather than the alerts the PR introduced.
That evidence is sound and it is also the problem. A check that is red for everyone is a check nobody reads, and "we have many of these" is exactly what makes one more read as normal. The next PR that genuinely introduces a fourteenth alert arrives on a cell that has looked the same since August.
This is the same failure this repository has already paid for elsewhere, in the other direction: gate-112 printed FAIL on a run that did not fail, and two readers counted a failure that had not happened (#729). Here a real high severity finding sits inside a signal everyone has learned to step over. A check that always says the same thing carries no information either way.
What would close this
One of three, decided rather than defaulted:
- Fix them. Scope the cache writes so the poisonable steps cannot reach them, or drop caching from the jobs that run untrusted code. Thirteen sites in one file, one fix shape.
- Dismiss them with a reason, per alert or via a rule configuration, so the cell goes green and a new alert is visible the day it lands. A dismissal that states why is a decision; a permanently red cell is not.
- Change what the PR check reports, so it distinguishes alerts introduced by the diff from alerts present in the base. That is the only option that fixes the reading problem without touching the alerts themselves.
Option 2 or 3 restores the signal in an afternoon. Option 1 is the one that removes the finding. Doing none of them keeps a month old high severity alert in a place where its own age is the argument for ignoring it.
Not in scope here
py/bad-tag-filter and the two py/stack-trace-exposure alerts are unrelated to the cache family and are listed above only so the total is honest.
Filed after #736 was merged past a red CodeQL cell. The merge was right and the alert is inherited rather than introduced, and that is precisely the problem worth writing down: this cell has been red for a month, it is red on every PR, and the reason it is safe to merge past is now discovered by hand each time.
What is actually open
Queried today from the code scanning API, all state
open:actions/cache-poisoning/poisonable-stepactions/cache-poisoning/direct-cachepy/bad-tag-filterpy/stack-trace-exposureAll 13 cache poisoning alerts are in one file,
.github/workflows/quality.yml, and all 13 were created on 13 or 16 August:The rule is Cache Poisoning via execution of untrusted code. The shape is the familiar one: a job that runs repository code, in a context that can write the Actions cache, on a workflow that is
pull_request-triggered.quality.ymlis consumed by all 21 core apps, so whatever the right answer is, it is the same answer 21 times.Why it needs an issue rather than a triage
The alerts were not suppressed and nobody has decided they are acceptable. What has happened instead is that each merge rediscovers, individually, that the red is old. For #736 the evidence was: alerts created a month before the branch existed, a branch first pushed the previous afternoon, a diff touching no workflow file at all, and a
pull_requestcode scanning check that reports the alerts present in the merge commit rather than the alerts the PR introduced.That evidence is sound and it is also the problem. A check that is red for everyone is a check nobody reads, and "we have many of these" is exactly what makes one more read as normal. The next PR that genuinely introduces a fourteenth alert arrives on a cell that has looked the same since August.
This is the same failure this repository has already paid for elsewhere, in the other direction: gate-112 printed
FAILon a run that did not fail, and two readers counted a failure that had not happened (#729). Here a real high severity finding sits inside a signal everyone has learned to step over. A check that always says the same thing carries no information either way.What would close this
One of three, decided rather than defaulted:
Option 2 or 3 restores the signal in an afternoon. Option 1 is the one that removes the finding. Doing none of them keeps a month old high severity alert in a place where its own age is the argument for ignoring it.
Not in scope here
py/bad-tag-filterand the twopy/stack-trace-exposurealerts are unrelated to the cache family and are listed above only so the total is honest.