Skip to content

ci: stop claiming egress-block on jobs that do not enforce it - #489

Merged
allxsmith merged 1 commit into
mainfrom
ci/487-truthful-egress-claims
Aug 7, 2026
Merged

allxsmith merged 1 commit into
mainfrom
ci/487-truthful-egress-claims

Conversation

@allxsmith

@allxsmith allxsmith commented Aug 7, 2026 •

Copy link
Copy Markdown
Owner

Comment-only. Makes the workflow files stop asserting a security control that is not running.

Why

While carrying out #456's audit-to-block obligation I found that harden-runner has never
enforced egress-policy: block in this repo. It arms block mode by reading an Actions cache
entry; GitHub made that cache read-only for untrusted triggers (issues, issue_comment,
pull_request, i.e. all of these workflows), and an unguarded new URL() on the resulting miss
fails open to audit, announcing it with one core.info line. Evidence, root cause from the
pinned action source, the measured endpoint list and the fix are in #487.

So three files described a control that does not exist, and the review checklist in
.github/CLAUDE.md ends on exactly that failure mode: "Security comments claim exactly what the
mechanism delivers. No more."

What changes

Nothing executable. No egress-policy value, no permissions: block, no allowlist, no logic.
Verified by parsing all three workflows after the edit: same jobs, same policy values
(ai-scan block, claude-repro block, ai-triage audit).

File Claim removed
claude-repro.yml Named egress-block as one of the two real controls behind I1, in the same comment that carefully demotes the credential check to a backstop. I1 rests on two legs, not three.
ai-scan.yml "harden-runner blocks egress" in the security header.
.github/CLAUDE.md Rule 10 and the I1 summary described block as the resting state without noting it is inert here.
ai-triage.yml The FOLLOW-UP asking for an audit-to-block flip, now known to be a no-op.

The ai-triage comment gains something concrete in its place: a real session reaches nine hosts
and the allowlist is missing three of them (claude.ai, downloads.claude.ai, and the CLI's
telemetry endpoint), so that flip would have broken triage at the Claude CLI download rather than
hardening it. The original decision in #361 to introduce this job at audit was right, for a
better reason than the one recorded at the time.

Declared policies and allowlists are left untouched so that closing #487 needs no edit here.

Not in this PR, on purpose

The fail-closed guard that would catch a future silent downgrade. harden-runner writes its
effective config after the downgrade decision, so this works:

jq -e '.egress_policy == "block"' /home/agent/agent.json

It fails every AI run until enforcement is actually restored, which is the entire point of it, so
it has to land with the fix in #487 rather than ahead of it.

Review notes

  • Contract-relevant per .github/CLAUDE.md: this touches the I1 rationale and rule 10, which is
    middle-row ("name the invariant at stake, confirm it holds, then act"). I1 itself is unchanged
    and still holds. Its two remaining legs, no execution primitive in the drafting job and the
    token never sharing a job with publish, are both real and both verified in the Post-merge obligations for the AI repro + security-scan automation (#361) #456 canary.
    What changed is the description, which had a third leg that was never load-bearing.
  • This is a defense-in-depth regression, not an open exfiltration path.
  • Upstream: step-security/harden-runner#675,
    open since 2026-07-14 with no maintainer response.

Refs #487, #456

Summary by CodeRabbit

  • Documentation
    • Updated security guidance to clarify that network egress blocking is not currently enforced.
    • Documented the effective reliance on restricted tools and credential checks.
    • Added details about incomplete endpoint allowlists, audit-mode fallback behavior, and required verification logs.
    • Clarified that egress blocking must not be treated as an active control until the underlying issue is resolved.

harden-runner has never enforced `egress-policy: block` in this repo. It arms
block mode by reading an Actions cache entry, GitHub made that cache read-only
for untrusted triggers, and an unguarded `new URL()` on the resulting miss fails
open to `audit` with a single `core.info` line. Root cause, evidence and fix are
in #487.

Comments only. No policy value, permission, allowlist or logic changes, so
behaviour is identical before and after. What changes is that the files stop
asserting a control that is not running:

- claude-repro.yml named egress-block as one of the two *real* controls behind
  I1, in the same comment that carefully demotes the credential check to a
  backstop. I1 rests on two legs, not three.
- ai-scan.yml claimed "harden-runner blocks egress" in its security header.
- .github/CLAUDE.md rule 10 and the I1 summary described block as the resting
  state for new jobs without noting that block is inert here.
- ai-triage.yml's FOLLOW-UP asked for an audit-to-block flip that is now known
  to be a no-op. Replaced with the measured endpoint gap: a real session
  reaches nine hosts and the allowlist is missing three of them, so the flip
  would have broken triage at the Claude CLI download rather than hardening it.

The allowlists are left as they are and the declared policies are unchanged, so
closing #487 needs no edit here.

Found while carrying out #456's audit-to-block obligation. The fail-closed
assertion that would catch a future silent downgrade
(`jq -e '.egress_policy == "block"' /home/agent/agent.json`) is deliberately not
in this commit: it fails every AI run until enforcement is restored, so it has
to land with the fix in #487.

Refs #487, #456
Copilot AI balanced review requested due to automatic review settings August 7, 2026 01:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 456d8fbd-3c14-4d86-971d-b781dc79d1a7

📥 Commits

Reviewing files that changed from the base of the PR and between 6b57479 and 32fadf3.

📒 Files selected for processing (4)
  • .github/CLAUDE.md
  • .github/workflows/ai-scan.yml
  • .github/workflows/ai-triage.yml
  • .github/workflows/claude-repro.yml

Walkthrough

The changes update repository and workflow security documentation. They state that harden-runner egress blocking falls back to audit mode, endpoint allowlists are incomplete, and tool restrictions and credential checks remain the documented controls.

Changes

Egress control documentation

Layer / File(s) Summary
Security invariant and harden-runner guidance
.github/CLAUDE.md, .github/workflows/claude-repro.yml
The documentation removes egress blocking as an active invariant guarantee and records audit fallback, incomplete allowlists, required log checks, tool restrictions, and credential checks.
Workflow security comments
.github/workflows/ai-scan.yml, .github/workflows/ai-triage.yml
Workflow comments document measured hosts, omitted endpoints, and the current block to audit behavior without changing workflow configuration.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related issues

Possibly related PRs

Suggested labels: documentation

Suggested reviewers: copilot, claude

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states that the PR removes inaccurate egress-block claims from CI jobs.
Description check ✅ Passed The description clearly explains the comment-only scope, affected files, rationale, validation, related issues, and deferred work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/487-truthful-egress-claims

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://fca5dac4.bestax.pages.dev

@allxsmith
allxsmith merged commit de3cbea into main Aug 7, 2026
17 checks passed
@allxsmith
allxsmith deleted the ci/487-truthful-egress-claims branch August 7, 2026 01:47
@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 5.8.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 4.0.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 1.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 2.0.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants