fix: keep egress-policy=block when the cache host can't be resolved (#675) - #676
Draft
JPHutchins wants to merge 1 commit into
Draft
fix: keep egress-policy=block when the cache host can't be resolved (#675)#676JPHutchins wants to merge 1 commit into
JPHutchins wants to merge 1 commit into
Conversation
Under egress-policy: block, harden-runner fetches the harden-runner-cacheKey cache entry only to discover the cache blob host and add it to the allowlist. When that entry does not exist (a cold cache, or a repo whose bootstrap saveCache lost the reserve race), GetCacheEntryDownloadURL returns no download URL, so `new URL(undefined)` throws and the catch silently downgraded block -> audit. The job then ran with no egress enforcement while the YAML said block: a fail-open in a security control (step-security#675). A cache-host resolution miss is a normal, expected condition and must not disable the user's egress policy. Keep block (fail closed) and emit a warning in both the v2 and v1 cache-service branches; the cache host is only needed to allowlist harden-runner's own cache traffic. Refs: step-security#675 Co-Authored-By: claude-opus-4-8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qgqy11vvMbUtCmrBML85sD
JPHutchins
marked this pull request as draft
July 15, 2026 05:32
Author
|
Moved to draft to avoid LLM slop merge. Consider as proof of concept. |
JPHutchins
added a commit
to JPHutchins/code-review
that referenced
this pull request
Jul 15, 2026
…rges harden-runner's egress-policy: block silently degrades to audit when it cannot resolve the Actions cache host during arming (a cold cache, or a lost cache reservation race): GetCacheEntryDownloadURL returns no URL, new URL(undefined) throws, and the catch downgrades block -> audit. The job then runs with no egress enforcement while the YAML says block (step-security/harden-runner#675). The #72 canary catches this and fails closed, so review jobs on repos with a cold harden-runner cache (e.g. jphfmt) get no review at all. Pin both harden-runner steps in the reusable workflow and the copy-paste example to JPHutchins/harden-runner@ee143ec (v2.20.0 + the fail-closed fix), which keeps block instead of downgrading. Validated on jphfmt: on the cold cache-reservation race the official action downgrades to audit and leaks egress while the fork keeps block and the egress canary is blocked. Fix is PR'd upstream (step-security/harden-runner#676); revert to the fixed official release once merged. Refs: #79, step-security/harden-runner#675, step-security/harden-runner#676 Co-Authored-By: claude-opus-4-8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qgqy11vvMbUtCmrBML85sD
JPHutchins
added a commit
to JPHutchins/code-review
that referenced
this pull request
Jul 15, 2026
…rges (#80) harden-runner's egress-policy: block silently degrades to audit when it cannot resolve the Actions cache host during arming (a cold cache, or a lost cache reservation race): GetCacheEntryDownloadURL returns no URL, new URL(undefined) throws, and the catch downgrades block -> audit. The job then runs with no egress enforcement while the YAML says block (step-security/harden-runner#675). The #72 canary catches this and fails closed, so review jobs on repos with a cold harden-runner cache (e.g. jphfmt) get no review at all. Pin both harden-runner steps in the reusable workflow and the copy-paste example to JPHutchins/harden-runner@ee143ec (v2.20.0 + the fail-closed fix), which keeps block instead of downgrading. Validated on jphfmt: on the cold cache-reservation race the official action downgrades to audit and leaks egress while the fork keeps block and the egress canary is blocked. Fix is PR'd upstream (step-security/harden-runner#676); revert to the fixed official release once merged. Refs: #79, step-security/harden-runner#675, step-security/harden-runner#676 Claude-Session: https://claude.ai/code/session_01Qgqy11vvMbUtCmrBML85sD Co-authored-by: claude-opus-4-8 <noreply@anthropic.com>
JPHutchins
added a commit
to JPHutchins/code-review
that referenced
this pull request
Jul 15, 2026
Pins harden-runner to the fail-closed fork (JPHutchins/harden-runner@ee143ec) until step-security/harden-runner#676 merges, so block-mode reviews on repos with a cold harden-runner cache (e.g. jphfmt) enforce egress instead of fail-closing at the canary. See #79. Co-Authored-By: claude-opus-4-8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qgqy11vvMbUtCmrBML85sD
JPHutchins
added a commit
to JPHutchins/jphfmt
that referenced
this pull request
Jul 15, 2026
Pins the fail-closed harden-runner fork (JPHutchins/harden-runner@ee143ec) so block-mode egress enforces on a cold harden-runner cache instead of silently degrading to audit. See JPHutchins/code-review#79 and step-security/harden-runner#676. Co-Authored-By: claude-opus-4-8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qgqy11vvMbUtCmrBML85sD
JPHutchins
added a commit
to JPHutchins/camas
that referenced
this pull request
Jul 15, 2026
Pins the fail-closed harden-runner fork (JPHutchins/harden-runner@ee143ec) so block-mode egress enforces on a cold harden-runner cache instead of silently degrading to audit. See JPHutchins/code-review#79 and step-security/harden-runner#676. Co-Authored-By: claude-opus-4-8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qgqy11vvMbUtCmrBML85sD
JPHutchins
added a commit
to JPHutchins/cerive
that referenced
this pull request
Jul 15, 2026
Pins the fail-closed harden-runner fork (JPHutchins/harden-runner@ee143ec) so block-mode egress enforces on a cold harden-runner cache instead of silently degrading to audit. See JPHutchins/code-review#79 and step-security/harden-runner#676. Co-Authored-By: claude-opus-4-8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qgqy11vvMbUtCmrBML85sD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Under
egress-policy: block, harden-runner must never silently downgrade itself toaudit. Today it does, whenever it can't resolve the Actions cache host during arming. This PR makes that path fail closed (keepblock) instead of fail open.Fixes #675.
Why
In
src/setup.ts, block-mode arming fetches theharden-runner-cacheKeycache entry only to discover the cache blob host and add it to the allowlist:When the cache entry is absent — a cold cache, or (commonly) when the bootstrapping
saveCachea few lines above loses the reservation race (Unable to reserve cache with key harden-runner-cacheKey, another job may be creating this cache) so the entry is never created —GetCacheEntryDownloadURLreturns nosignedDownloadUrl,new URL(undefined)throwsTypeError: Invalid URL, and thecatchsetsegress_policy = "audit". The job then runs with no egress enforcement while the workflow saysblock, and the only signal is oneinfoline. That's a fail-open in a security control (details and repro in #675). The v1 branch has the identical pattern.The change
Both the v2 and v1 cache-service branches now keep
blockand emit acore.warningon a cache-host resolution miss, instead of downgrading. The cache host is only needed to allowlist harden-runner's own cache traffic; failing to resolve it must not disable the user's configured egress policy. (Left the policy-store 5xx fallback untouched — that's a separate path.)Validation
Reproduced and fixed on a repo that hits the reservation race, running a burst of concurrent
block-mode jobs (example.comegress canary;example.comis never allowlisted, so connected = enforcement is off):EgressPolicystep-security/harden-runner@v2.20.0auditblockSame repo, same race, same commit — the official action downgraded to
auditand let egress through; this branch keptblockand the canary was blocked. The jobs that won the reservation race resolved the cache host and heldblockon both, unchanged.dist/is rebuilt (npm run build).Note
I've implemented this as fail-closed by default, since silently disabling a configured security control is the bug. If you'd prefer it gated behind an opt-in input (e.g.
fail-on-policy-downgrade: true, as floated in #675), happy to adjust.Warning
LLM Disclosure
This PR was authored by claude-opus-4-8 on behalf of @JPHutchins, after tracing the fail-open in
dist/pre/index.js/src/setup.tsand validating the fix against the reservation-race repro described in #675.