Skip to content

Workflows permission on demand and a Team probe that can see private repositories - #16

Merged
immakermatty merged 3 commits into
mainfrom
agent/GH15-workflows-permission
Oct 2, 2026
Merged

immakermatty merged 3 commits into
mainfrom
agent/GH15-workflows-permission

Conversation

@immakermatty

@immakermatty immakermatty commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Why

A Team Workspace acts on GitHub through this broker. Its installation tokens never asked for workflows: write. Any push of a commit that adds or changes .github/workflows/ was therefore refused by GitHub, even though the Team holds a write grant and a human member of that Team could push the same commit. In practice work stayed stuck on the Workspace disk until an admin pushed it by hand (#15).

What changes

  • mintToken asks for the base set (actions: write, checks: read, contents: write, pull_requests: write) plus workflows: write only when the reviewed policy's installation_permissions.workflows is write.
  • The response check now compares against exactly what was requested, plus GitHub's automatic metadata: read. Both an extra and a missing permission are still refused, including workflows returned when it was not requested.
  • AGENTS invariant 4, README and ARCHITECTURE document the optional permission and its security meaning. A workflow the Workspace writes can, in an eligible run, reference and exfiltrate the Actions secrets available to that run, subject to environment protections. That is the same capability GitHub already gives a Team member with a write grant.

Fix found while preparing the release: the Team probe could not see private repositories

The unreleased policy v2 Team gate (#13) mints a probe with only members: read. GitHub answers GET /organizations/{org}/team/{team}/repos/{owner}/{repo} with 404 for every private repository that token cannot see. I confirmed it live: the same request returns 200 once the probe also has metadata: read.

policy check --live against the three production policies (switched to schema v2 in a temp copy, run from operator custody):

Probe permissions Grants checked Result
members: read only 178 170 refused, only public repos passed
members: read + metadata: read 178 178 ok

Releasing main as-is would have refused nearly every token in every Organization. This PR adds metadata: read to TEAM_PROBE_PERMISSIONS and documents why. The probe stays short-lived, read-only and revoked.

What deliberately does not change

  • No new policy field or schema bump. installation_permissions already lists the exact accepted set, and the installation gate keeps comparing it exactly with the live installation.
  • Policies without workflows mint exactly what they mint today. The release can therefore be deployed to every Organization before any of them accepts the new App permission. Each Organization then opts in by accepting the permission and deploying a policy that declares it, in one short window. The exact installation gate makes that window unavoidable, and it is documented in the README.

Release

Verification

  • Live policy check --live on all three production policies: 178/178 ok (table above).
  • npm test: 56/56. The new test covers the request without workflows, the request with it, a response with workflows that was not requested, a response missing requested workflows, and an extra emails scope.
  • npm run check passes (license check, syntax, Worker dry-run).

Refs #15

🤖 Generated with Claude Code

…sion

A Team Workspace could not push commits touching .github/workflows/ because
installation tokens never asked for workflows: write. The token now asks for
it only when the reviewed policy's installation_permissions declares it, and
refuses a response outside the requested set, so this release can roll out
before any Organization accepts the new App permission.

Refs #15

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@agentrozjedemeai agentrozjedemeai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@immakermatty Exact-head review of 305b1db: the token request is policy-gated, the returned scope rejects both missing and extra permissions, and the installation comparison remains exact. I ran npm ci, npm test (56/56), npm run check (pass), and git diff --check (pass).

Documentation change requested — ARCHITECTURE.md:43-47 (and the same claim in the PR description): “A changed workflow runs with that repository’s Actions secrets” overstates GitHub’s behavior. Secrets are not automatically injected into every changed workflow: jobs must reference them, fork-pull-request and Dependabot events withhold Actions secrets, and environment secrets can require approval. The risk is real: a writable workflow executed in an eligible context can reference/exfiltrate available repository secrets. Please qualify the sentence along those lines so the public security note describes capability rather than guaranteed access. No code blocker found.

…isible

With members: read alone GitHub answers the Team repository check with 404 for
every private repository the probe cannot see. A live policy check against the
three production policies refused 170 of 178 real write grants; with
metadata: read all 178 pass.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@immakermatty immakermatty changed the title Ask for workflows: write when the policy declares the accepted permission Workflows permission on demand and a Team probe that can see private repositories Oct 2, 2026

@agentrozjedemeai agentrozjedemeai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@immakermatty Exact-head review of 99bc49c. CHANGES REQUESTED on the public security claim in ARCHITECTURE.md:43–47 (also in this PR description): “A changed workflow runs with that repository’s Actions secrets” is not guaranteed. Editing a workflow does not itself make it run or automatically pass it secrets. Jobs must reference accessible secrets in an eligible run; fork-PR and Dependabot events withhold ordinary Actions secrets, while protected environment secrets require approval. Please frame this as capability/risk instead: a writable workflow can access or exfiltrate available repository/organization Actions secrets in an eligible run, subject to environment protections. The prior review on 305b1db raised the same blocker; this new head fixes the Team probe but leaves this sentence unchanged. README.md:144 also still describes the probe as members: read without mentioning the newly added metadata: read; please make that earlier explanation consistent with the later section. Code gate looks sound: workflows is requested only when the parsed policy declares it; the response comparison rejects both missing requested and extra permissions; the live installation comparison stays exact. In this isolated exact-head clone, npm ci, npm test (56/56), npm run check (license/syntax/Worker dry-run) and git diff --check passed. I did not independently run the production-policy live probe.

…rywhere

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@agentrozjedemeai agentrozjedemeai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@immakermatty Re-review of exact head 3f9824f: APPROVED. The only new commit changes ARCHITECTURE.md and README.md. The workflow security note and PR description now describe conditional capability rather than automatic execution or secret access, including fork/Dependabot and protected-environment caveats. The Team probe is consistently documented as members: read plus metadata: read. No code changes since the earlier sound code verdict. In a fresh isolated clone, npm ci, npm test (56/56), npm run check (license, syntax, Worker dry-run), and git diff --check passed. Current-head CI is green and there are no unresolved review threads or pending reviewer requests. The production-policy live probe (178/178) is author-reported, not independently rerun in this review. Review only; no merge.

@immakermatty
immakermatty merged commit 3e7970d into main Oct 2, 2026
3 checks passed
@immakermatty
immakermatty deleted the agent/GH15-workflows-permission branch October 2, 2026 22:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants