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
{{ message }}
Repository navigation
Commit e0aa0f8
Browse filesBrowse the repository at this point in the historyBrowse files
27Bslash6
committed
ci: exact-label runner allow-list, refuse unreadable runner forms (LAB-3500)
Kody flagged that the hosted-prefix pattern admitted a pool label renamed
`ubuntu-<anything>`. Allow-list the exact labels in use instead
(`^(ubuntu|macos|windows)-latest$`) — smaller than the prefix pattern and
not a second, staler copy of GitHub's image table (Kody's enumerated list
already omits ubuntu-26.04, macos-26-intel, windows-2025-vs2026, xcode-27).
Expert panel on the delta found four shapes that set a job's runner where
the guard could not read it and exited 0: flow-style `{runs-on: x}`, a
matrix built by `${{ fromJSON(...) }}` (the comment claimed "no fromJSON"
without enforcing it), a job calling a reusable workflow in another repo,
and quoted or upper-cased keys. Each is now an error, not a skip; keys and
values are lower-cased before matching. Rejected: banning
`continue-on-error` repo-wide (editing the guard job is deletion-class and
the ban has real cost) and YAML obfuscation forms (`? runs-on`, escapes) —
deliberate acts the guard is documented not to defend against; the
server-side control is LAB-1161 stage 2.
Verified with the job's exact program under mawk 1.3.4: clean tree exit 0;
42 fixtures (30 bad → ::error + exit 1, 12 good → exit 0); the pre-PR main
workflows fail on exactly their 19 `runs-on: cachekit` lines.
printf "::error file=%s,line=%d::runner set where the drift guard cannot read it — write `runs-on: <label>` / `os: [<labels>]` inline, spell matrices out (no fromJSON), call reusable workflows only from ./.github/workflows/ (LAB-3500)\n", FILENAME, FNR
v = $0; sub(/^[^:]*:[[:space:]]*/, "", v); sub(/[[:space:]]+$/, "", v)
317
330
if (v ~ /^["']?\$\{\{[[:space:]]*matrix\.os[[:space:]]*\}\}["']?$/) next
331
+
if (v ~ /^\[/ && v !~ /\]$/) v = ""
318
332
gsub(/[][ "']/, "", v)
319
333
n = split(v, items, ",")
320
334
ok = (n > 0)
321
-
for (i = 1; i <= n; i++) if (items[i] !~ /^(ubuntu|macos|windows)-[a-z0-9.-]+$/) ok = 0
335
+
for (i = 1; i <= n; i++) if (items[i] !~ /^(ubuntu|macos|windows)-latest$/) ok = 0
322
336
if (!ok) {
323
-
printf "::error file=%s,line=%d::runner value \"%s\" is not a GitHub-hosted label — this public repo never runs on the self-hosted pool (LAB-1161)\n", FILENAME, FNR, (v == "" ? "<empty / block form>" : v)
337
+
printf "::error file=%s,line=%d::runner value \"%s\" is not an allow-listed GitHub-hosted label — this public repo never runs on the self-hosted pool (LAB-1161); adopting a new hosted image means extending the allow-list in this job\n", FILENAME, FNR, (v == "" ? "<value not inline on this line>" : v)
0 commit comments