Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
ba507a6
ci: enforce egress-block on the AI workflows instead of declaring it
allxsmith Aug 27, 2026
eba63e7
ci: point the audit-mode harden-runner comments at the follow-up issue
allxsmith Aug 27, 2026
9e428b5
ci: assert the firewall is live, and drop the dead host that disabled it
allxsmith Aug 28, 2026
f336657
ci: note that the consumer-sbom assertion runs per matrix leg
allxsmith Aug 28, 2026
4ce6ef8
ci: scope the downgrade claim to untrusted triggers, unbreak an md he…
allxsmith Aug 28, 2026
06feb79
ci: stop the assertion comments claiming more than the assertion proves
allxsmith Aug 28, 2026
6aead4d
ci: fix a missing release host, a fail-open verdict path, and stale s…
allxsmith Aug 28, 2026
d8a3946
ci: unmangle the I1 scoping sentence, decline the liveness check on t…
allxsmith Aug 28, 2026
80ac29c
docs: record that a PR modifying claude-review.yml cannot be deep-rev…
allxsmith Aug 28, 2026
9387293
ci: stop the assertion turning a vendor outage into a repo-wide failure
allxsmith Aug 28, 2026
1fe363b
ci: charge the scan budget after enforcement is proven, not before
allxsmith Aug 28, 2026
966d152
Merge branch 'main' into ci/487-enforce-egress-block
allxsmith Aug 28, 2026
edf0759
ci: stop the telemetry comment borrowing a threat model it does not have
allxsmith Aug 28, 2026
a648268
ci: let the gate emit its outputs when harden-runner itself fails
allxsmith Aug 28, 2026
26ba6e4
ci: stop the inventory calling code-executing jobs API-only, again
allxsmith Aug 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
279 changes: 247 additions & 32 deletions .github/CLAUDE.md

Large diffs are not rendered by default.

330 changes: 282 additions & 48 deletions .github/workflows/ai-scan.yml

Large diffs are not rendered by default.

221 changes: 190 additions & 31 deletions .github/workflows/ai-triage.yml

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions .github/workflows/bestaxbot-reply.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ jobs:
issues: write # issue-comment replies
id-token: write # OIDC exchange for the subscription token
steps:
# AUDIT, not block, and rule 10's "existing live job" clause is why: this
# job checks out code, installs dependencies and runs a Claude session
# holding both bestaxbot's PAT and the OAuth token, and none of that egress
# has ever been measured. A guessed allowlist would break replies on the
# first miss; audit mode reports every endpoint the run touches without
# refusing any, which is what produces the list a block flip needs. That
# flip is the follow-up rule 10 owes (#578) — audit is a starting point
# here, not a resting place.
- name: Harden runner
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
with:
egress-policy: audit
Comment thread
allxsmith marked this conversation as resolved.
Resolved

# Layer 2 (authoritative): author_association can be COLLABORATOR with
# only read access. Re-check the LIVE role and require write/triage+.
- name: Check trigger permission
Expand Down Expand Up @@ -157,6 +170,27 @@ jobs:

- name: Run Claude (respond as bestaxbot)
if: steps.perm.outputs.allowed == 'true'
# Telemetry is denied, never allow-listed: the CLI's Datadog intake host
# stays off every allowlist in this repo AND the CLI is told not to emit
# it (#487). It also covers feature-flag evaluation, which is why
# statsig.anthropic.com is gone.
#
# On this `audit` job the point is the MEASUREMENT: audit mode exists to
# produce the endpoint list a block flip will use (#578), and leaving
# telemetry on would put the Datadog host in that report, inviting whoever
# reads it to allow-list a host we have just decided to deny.
#
# A step `env:` rather than the action's `settings:` input. `settings:` is
# written to the USER-level ~/.claude/settings.json, which a project-level
# .claude/settings.json in the workspace overrides. This job does NOT check
# out PR-branch code, so nothing in its workspace is attacker-controlled
# today — state that accurately rather than borrowing a sibling's threat
# model. The env form is used so the control does not DEPEND on that:
# claude-review.yml and claude-pr-loop.yml do check out PR branches and
# share this shape, and a checkout change here would silently move this job
# into their class. Do not move this back under `with:`.
env:
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1'
uses: anthropics/claude-code-action@51c47629174b5dbca955cf93690fd39c8a41dadf # v1
with:
# Respond as the bestaxbot machine account so replies/commits come
Expand Down
35 changes: 35 additions & 0 deletions .github/workflows/claude-implement.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
# AUDIT, not block, and rule 10's "existing live job" clause is why: this
# job checks out a branch, installs dependencies and runs a Claude session
# with a model token, and none of that egress has ever been measured. A
# guessed allowlist would break the job on its first miss; audit mode
# reports every endpoint the run touches without refusing any, which is
# what produces the list a block flip needs. That flip is the follow-up
# rule 10 owes (#578) — audit is a starting point here, not a resting
# place. Six jobs run repo code alongside the model token (rule 10 lists
# them); this is one of them, not the only one.
- name: Harden runner
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
with:
egress-policy: audit

# Anyone with triage access or higher may start the loop; everyone
# else (including issue authors whose template applied the label) is
# a silent no-op that spends no Claude usage.
Expand Down Expand Up @@ -90,6 +104,27 @@ jobs:

- name: Run Claude (implement issue)
if: steps.perm.outputs.allowed == 'true'
# Telemetry is denied, never allow-listed: the CLI's Datadog intake host
# stays off every allowlist in this repo AND the CLI is told not to emit
# it (#487). It also covers feature-flag evaluation, which is why
# statsig.anthropic.com is gone.
#
# On this `audit` job the point is the MEASUREMENT: audit mode exists to
# produce the endpoint list a block flip will use (#578), and leaving
# telemetry on would put the Datadog host in that report, inviting whoever
# reads it to allow-list a host we have just decided to deny.
#
# A step `env:` rather than the action's `settings:` input. `settings:` is
# written to the USER-level ~/.claude/settings.json, which a project-level
# .claude/settings.json in the workspace overrides. This job does NOT check
# out PR-branch code, so nothing in its workspace is attacker-controlled
# today — state that accurately rather than borrowing a sibling's threat
# model. The env form is used so the control does not DEPEND on that:
# claude-review.yml and claude-pr-loop.yml do check out PR branches and
# share this shape, and a checkout change here would silently move this job
# into their class. Do not move this back under `with:`.
env:
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1'
uses: anthropics/claude-code-action@51c47629174b5dbca955cf93690fd39c8a41dadf # v1
with:
# Run GitHub operations as the bestaxbot machine account (like Bun's
Expand Down
64 changes: 64 additions & 0 deletions .github/workflows/claude-pr-loop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,23 @@ jobs:
id-token: write # OIDC exchange for claude[bot] auth
actions: write # read CI logs + self-dispatch in the terminal step
steps:
# AUDIT, not block, and rule 10's "existing live job" clause is why: this
# job checks out a PR branch, installs dependencies and runs a Claude
# session with a model token, and none of that egress has ever been
# measured. A guessed allowlist would break the loop on its first miss;
# audit mode reports every endpoint the run touches without refusing any,
# which is what produces the list a block flip needs. That flip is the
# follow-up rule 10 owes (#578) — audit is a starting point here, not a
# resting place. Six jobs run repo code alongside the model token (rule 10
# lists them); this is one of them, not the only one.
#
# The sibling sweep/gate/handoff/halt jobs make GitHub API calls only and
# carry no harden-runner; only `fix` and `verify` execute repo code.
- name: Harden runner
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
with:
egress-policy: audit

- name: Checkout PR branch
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
Expand Down Expand Up @@ -359,6 +376,25 @@ jobs:

- name: Run Claude (fix)
id: claude
# Telemetry is denied, never allow-listed: the CLI's Datadog intake host
# stays off every allowlist in this repo AND the CLI is told not to emit
# it (#487). It also covers feature-flag evaluation, which is why
# statsig.anthropic.com is gone.
#
# On this `audit` job the point is the MEASUREMENT: audit mode exists to
# produce the endpoint list a block flip will use (#578), and leaving
# telemetry on would put the Datadog host in that report, inviting whoever
# reads it to allow-list a host we have just decided to deny.
#
# A step `env:` rather than the action's `settings:` input, and here that
# is load-bearing rather than tidiness: `settings:` is written to the
# USER-level ~/.claude/settings.json, which a project-level
# .claude/settings.json in the workspace OVERRIDES — and this job checks
# out PR-branch code, so that file is attacker-controlled. A process
# environment variable is not overridable that way. Do not move this back
# under `with:`.
env:
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1'
uses: anthropics/claude-code-action@51c47629174b5dbca955cf93690fd39c8a41dadf # v1
with:
# Fix/refute as the bestaxbot machine account (Stage 2): its
Expand Down Expand Up @@ -614,6 +650,15 @@ jobs:
id-token: write # OIDC exchange for claude[bot] auth
actions: write # self-dispatch in the continue step
steps:
# AUDIT, not block — same reasoning as the `fix` job above: this job checks
# out a PR branch, installs dependencies and runs a Claude session with a
# model token, and its egress is unmeasured. Audit mode produces the list a
# block flip needs. Tracked as the follow-up rule 10 owes (#578).
- name: Harden runner
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
with:
egress-policy: audit

- name: Checkout PR branch
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
Expand Down Expand Up @@ -644,6 +689,25 @@ jobs:

- name: Run Claude (verify fixes)
id: claude
# Telemetry is denied, never allow-listed: the CLI's Datadog intake host
# stays off every allowlist in this repo AND the CLI is told not to emit
# it (#487). It also covers feature-flag evaluation, which is why
# statsig.anthropic.com is gone.
#
# On this `audit` job the point is the MEASUREMENT: audit mode exists to
# produce the endpoint list a block flip will use (#578), and leaving
# telemetry on would put the Datadog host in that report, inviting whoever
# reads it to allow-list a host we have just decided to deny.
#
# A step `env:` rather than the action's `settings:` input, and here that
# is load-bearing rather than tidiness: `settings:` is written to the
# USER-level ~/.claude/settings.json, which a project-level
# .claude/settings.json in the workspace OVERRIDES — and this job checks
# out PR-branch code, so that file is attacker-controlled. A process
# environment variable is not overridable that way. Do not move this back
# under `with:`.
env:
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1'
uses: anthropics/claude-code-action@51c47629174b5dbca955cf93690fd39c8a41dadf # v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
Expand Down
Loading
Loading