Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(ci): scope per-job permissions in marketplace-governance example#2173

Merged
imran-siddique merged 1 commit into
microsoft:mainfrom
aegis-initiative:fix/ci-plugin-governance-per-job-permissions
May 12, 2026
Merged

fix(ci): scope per-job permissions in marketplace-governance example#2173
imran-siddique merged 1 commit into
microsoft:mainfrom
aegis-initiative:fix/ci-plugin-governance-per-job-permissions

Conversation

@finnoybu

Copy link
Copy Markdown
Contributor

Summary

examples/marketplace-governance/.github/workflows/plugin-governance.yml is a downstream-facing example — consumers copy it into their own repos as a starting point — so its permission hygiene shapes the default behavior in many production CI pipelines that adopt the toolkit.

Two issues:

  1. Workflow-level pull-requests: write is unused. None of the three jobs (validate-manifest, evaluate-policy, governance-verify) comments on or modifies a PR. They run policy validation, evaluate plugins, upload an artifact, and write to GITHUB_STEP_SUMMARY (which needs no extra scope).
  2. No per-job permissions: blocks. Every job inherits the workflow-level grants, which means a future copy-paste consumer that adds a write-scoped job inherits the over-broad grant by default.

Both apply to lines 33, 65, and 108 (the three job headers).

This is in the same spirit as #2138 (workflow shell-injection hardening) and #2141 (Gitleaks fork-PR skip) — example workflows are templates as much as they are code.

Change

  • Drop workflow-level pull-requests: write (no job uses it).
  • Keep workflow-level contents: read.
  • Add explicit permissions: { contents: read } to each of the three jobs.
  • Add a comment block at the top explaining the per-job scoping rationale for downstream readers — the whole point of an example workflow is to be learned from.

Verification

  • Diff is local to the example workflow file; nothing else in the repo touches this file.
  • actionlint parses cleanly (the workflow does not actually run on this repo's CI, since it triggers on plugins/** which doesn't exist here).
  • No job in this workflow needs any write scope to function — verified by reading every step.

Surfaced during independent audit conducted by @finnoybu (Ken Tannenbaum, AEGIS Initiative); [LOW, Infrastructure/CI].

`examples/marketplace-governance/.github/workflows/plugin-governance.yml`
is a downstream-facing example workflow — consumers copy it into their
own repos as a starting point — so its permission hygiene shapes the
default behavior in many production CI pipelines.

The original file granted workflow-level `pull-requests: write` and no
per-job `permissions:` blocks, which means:

- Every job inherits the workflow-level grants.
- The PR-write grant is over-broad: none of the three jobs actually
  comments on or modifies a PR. They run policy validation, evaluate
  plugins, upload an artifact, and write to GITHUB_STEP_SUMMARY (which
  needs no extra scope).

Apply principle of least privilege:

- Drop workflow-level `pull-requests: write` (unused by any job).
- Keep workflow-level `contents: read`.
- Add explicit `permissions: { contents: read }` per job so copy-paste
  consumers see the pattern and can't accidentally widen the scope by
  appending one write-scoped job to the file.

Add a comment block at the top explaining the rationale for downstream
readers — the whole point of an example workflow is to be learned from.
@github-actions

Copy link
Copy Markdown
🤖 AI Agent: security-scanner — View details

No security issues found.

@github-actions

Copy link
Copy Markdown
🤖 AI Agent: test-generator — View details

Test coverage looks good. No gaps identified.

@github-actions

Copy link
Copy Markdown
🤖 AI Agent: breaking-change-detector — API Compatibility

API Compatibility

Severity Change Impact
Low Dropped workflow-level pull-requests: write permission Future consumers may face issues if they expect write access for pull requests in their copied workflows.
Low Added per-job permissions: { contents: read } Changes the permission model for jobs, which may affect downstream consumers if they rely on inherited permissions.

@github-actions

Copy link
Copy Markdown
🤖 AI Agent: code-reviewer — View details

TL;DR: 0 blockers, 0 warnings. No issues found. Clean change.

@github-actions github-actions Bot added the size/S Small PR (< 50 lines) label May 12, 2026
@github-actions

Copy link
Copy Markdown
🤖 AI Agent: docs-sync-checker — Docs Sync

Docs Sync

  • README.md -- section on example workflows needs update
  • CHANGELOG.md -- missing entry for behavioral changes regarding permissions in example workflows

@github-actions

Copy link
Copy Markdown

🟡 Contributor Check: MEDIUM

Check Result
Profile MEDIUM
Credential NONE
Overall MEDIUM

Automated check by AGT Contributor Check.

@github-actions github-actions Bot added the needs-review:MEDIUM Contributor check flagged MEDIUM risk label May 12, 2026
@github-actions

Copy link
Copy Markdown

PR Review Summary

Check Status Details
🔍 Code Review ✅ Passed No issues found
🛡️ Security Scan ✅ Passed No issues found
🔄 Breaking Changes ✅ Completed Analysis complete
📝 Docs Sync ✅ Completed Analysis complete
🧪 Test Coverage ✅ Completed Analysis complete

Verdict: ✅ Ready for human review

@imran-siddique imran-siddique merged commit 60b429b into microsoft:main May 12, 2026
13 of 14 checks passed
MohammadHaroonAbuomar pushed a commit to MohammadHaroonAbuomar/agt-acs that referenced this pull request Jun 1, 2026
…icrosoft#2173)

`examples/marketplace-governance/.github/workflows/plugin-governance.yml`
is a downstream-facing example workflow — consumers copy it into their
own repos as a starting point — so its permission hygiene shapes the
default behavior in many production CI pipelines.

The original file granted workflow-level `pull-requests: write` and no
per-job `permissions:` blocks, which means:

- Every job inherits the workflow-level grants.
- The PR-write grant is over-broad: none of the three jobs actually
  comments on or modifies a PR. They run policy validation, evaluate
  plugins, upload an artifact, and write to GITHUB_STEP_SUMMARY (which
  needs no extra scope).

Apply principle of least privilege:

- Drop workflow-level `pull-requests: write` (unused by any job).
- Keep workflow-level `contents: read`.
- Add explicit `permissions: { contents: read }` per job so copy-paste
  consumers see the pattern and can't accidentally widen the scope by
  appending one write-scoped job to the file.

Add a comment block at the top explaining the rationale for downstream
readers — the whole point of an example workflow is to be learned from.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-review:MEDIUM Contributor check flagged MEDIUM risk size/S Small PR (< 50 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants