Skip to content

feat: add GitHub App-only permissions support#21511

Merged
pelikhan merged 11 commits intomainfrom
copilot/add-support-for-github-app-permissions
Mar 18, 2026
Merged

feat: add GitHub App-only permissions support#21511
pelikhan merged 11 commits intomainfrom
copilot/add-support-for-github-app-permissions

Conversation

Copy link
Contributor

Copilot AI commented Mar 18, 2026

The permissions: block only supported GitHub Actions GITHUB_TOKEN scopes. There was no way to declare permissions like members, administration, or environments that are exclusive to GitHub App installation tokens — and no validation requiring a GitHub App when such scopes are used.

Changes

New GitHub App-only permission scopes

  • Added 31 new PermissionScope constants covering repository, organization, and user-level GitHub App permissions (e.g., administration, members, environments, workflows, vulnerability-alerts, organization-members, team-discussions, codespaces, etc.)
  • Moved organization-projects from the GitHub Actions scope list to GitHub App-only (it was already being silently dropped from YAML rendering; now correctly classified)
  • Secrets-related scopes (secrets, dependabot-secrets, organization-secrets, codespaces-secrets) are intentionally excluded

Full GitHub App-only scope list

Repository-level: administration, environments, git-signing, vulnerability-alerts, workflows, repository-hooks, single-file, codespaces, repository-custom-properties

Organization-level: organization-projects, members, organization-administration, team-discussions, organization-hooks, organization-members, organization-packages, organization-self-hosted-runners, organization-custom-org-roles, organization-custom-properties, organization-custom-repository-roles, organization-announcement-banners, organization-events, organization-plan, organization-user-blocking, organization-personal-access-token-requests, organization-personal-access-tokens, organization-copilot, organization-codespaces

User-level: email-addresses, codespaces-lifecycle-admin, codespaces-metadata

Config types

  • PermissionsConfig embeds two separate types: GitHubActionsPermissionsConfig (standard GITHUB_TOKEN scopes) and GitHubAppPermissionsConfig (GitHub App-only scopes)

Rendering

  • RenderToYAML() skips all GitHub App-only scopes (they can't be set on GITHUB_TOKEN) via the new IsGitHubAppOnlyScope() helper; returns "" instead of a bare permissions: header when all scopes are skipped
  • convertPermissionsToAppTokenFields() maps all new scopes to permission-* inputs for actions/create-github-app-token, checking only explicitly-declared scopes (never shorthand-derived)

Validation

  • Compilation errors when any GitHub App-only permission is explicitly declared without a github-app configured anywhere in the workflow (tools.github.github-app, safe-outputs.github-app, or github-app:)
  • Shorthand permissions (read-all, write-all, all: read) do NOT trigger this validation
  • Compilation errors when write is requested for any GitHub App-only scope — all GitHub App-only permissions must be declared as read; write operations are performed via safe-outputs, not through declared permissions

Documentation

  • Updated docs/src/content/docs/reference/permissions.md with a new ### GitHub App-Only Permissions section listing all scopes by level, explaining that they are omitted from the compiled permissions: YAML and forwarded to actions/create-github-app-token, and documenting the compile-time validation rules

Example usage:

---
permissions:
  contents: read
  members: read          # GitHub App-only — requires github-app below
tools:
  github:
    github-app:
      app-id: ${{ vars.APP_ID }}
      private-key: ${{ secrets.APP_PRIVATE_KEY }}
---

The members scope is omitted from the workflow's permissions: YAML but passed as permission-members: read when minting the App token.

Original prompt

Add support for specifying permissions that are supported by GitHub-app but not github actions in the permissions object. For example orgs: read.

the reason is to allow a user to configuration advanced set of permissions beyond the github action token permissions, but still leveraging the same syntax.

Whenever such permission is used, the github.github-app must be provided as minting a token is mandatory.

Do a systematic review of github app vs github action permissions and fill the gaps.


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Copilot AI and others added 2 commits March 18, 2026 03:13
- Add 35 GitHub App-only PermissionScope constants (administration,
  members, organization-administration, secrets, environments, workflows,
  git-signing, vulnerability-alerts, repository-hooks, single-file,
  codespaces, dependabot-secrets, organization-hooks, organization-members,
  organization-packages, organization-secrets, organization-custom-org-roles,
  organization-custom-properties, organization-custom-repository-roles,
  organization-announcement-banners, organization-events, organization-plan,
  organization-user-blocking, organization-personal-access-token-requests,
  organization-personal-access-tokens, organization-copilot,
  organization-codespaces, email-addresses, codespaces-lifecycle-admin,
  codespaces-metadata, codespaces-secrets, repository-custom-properties,
  organization-administration, team-discussions, organization-self-hosted-runners)
- Move organization-projects from GitHub Actions scopes to GitHub App-only scopes
- Add GetAllGitHubAppOnlyScopes() and IsGitHubAppOnlyScope() functions
- Update RenderToYAML() to skip GitHub App-only scopes using IsGitHubAppOnlyScope()
- Update convertPermissionsToAppTokenFields() to map all new App-only permissions
- Update PermissionsConfig struct and parser/serializer with all new fields
- Add validateGitHubAppOnlyPermissions() validation requiring github-app config
- Register new validation in compiler pipeline
- Add comprehensive tests for all new functionality
- Fix test counts for write-all shorthand expansion

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…oryCustomProperties

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Add support for GitHub app permissions in configuration feat: add GitHub App-only permissions support Mar 18, 2026
Copilot AI requested a review from pelikhan March 18, 2026 03:18
// Supports both shorthand (read-all, write-all) and detailed scope-based permissions.
// In addition to standard GitHub Actions scopes, this also supports GitHub App-only scopes
// (e.g., members, administration) for use when a GitHub App is configured.
type PermissionsConfig struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

@create two types with inheritance to maintain them separate

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in 7fc28c6. PermissionsConfig now embeds two separate types:

  • GitHubActionsPermissionsConfig — standard GITHUB_TOKEN scopes
  • GitHubAppPermissionsConfig — GitHub App-only scopes

Field access is unchanged via Go embedding promotion.

@pelikhan pelikhan marked this pull request as ready for review March 18, 2026 03:30
Copilot AI review requested due to automatic review settings March 18, 2026 03:30
@pelikhan
Copy link
Contributor

@copilot Review comments

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support for declaring GitHub App-only permission scopes in the workflow permissions: configuration, ensuring those scopes are omitted from the rendered GitHub Actions YAML but are forwarded to actions/create-github-app-token, and enforcing validation that a GitHub App is configured when such scopes are used.

Changes:

  • Expanded PermissionScope to include many GitHub App-only scopes and added helpers to classify them.
  • Updated YAML rendering and GitHub App token minting to handle GitHub App-only scopes appropriately.
  • Added compiler-time validation (with tests) requiring a GitHub App configuration when GitHub App-only scopes are declared.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pkg/workflow/safe_outputs_app_config.go Maps permissions (including App-only scopes) into permission-* inputs for actions/create-github-app-token.
pkg/workflow/permissions_operations.go Skips GitHub App-only scopes during permissions: YAML rendering via IsGitHubAppOnlyScope.
pkg/workflow/permissions.go Adds GitHub App-only scopes, lists, and IsGitHubAppOnlyScope() helper.
pkg/workflow/github_app_permissions_validation.go New validation requiring GitHub App configuration when App-only scopes are used.
pkg/workflow/github_app_permissions_validation_test.go New tests for App-only scope classification, rendering, conversion, and validation behavior.
pkg/workflow/frontmatter_types.go Extends typed permissions config parsing/serialization to include App-only scopes.
pkg/workflow/compiler.go Wires the new App-only permissions validation into compilation.
pkg/workflow/permissions_operations_test.go Updates merge tests to reflect organization-projects reclassification and scope lists.
pkg/workflow/dangerous_permissions_validation_test.go Adjusts expected write-scope count after scope list changes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +36 to +39
// Find any GitHub App-only permission scopes that are set
var appOnlyScopes []PermissionScope
for _, scope := range GetAllGitHubAppOnlyScopes() {
if _, exists := permissions.Get(scope); exists {
Comment on lines 241 to 245
@@ -245,11 +245,120 @@ func convertPermissionsToAppTokenFields(permissions *Permissions) map[string]str
fields["permission-discussions"] = string(level)
Comment on lines +14 to 16
// GitHub Actions permission scopes (supported by GITHUB_TOKEN)
case "actions":
return PermissionActions
Comment on lines +260 to 265
// Skip GitHub App-only permissions - they are not valid GitHub Actions workflow permissions
// and cannot be set on the GITHUB_TOKEN. They are handled separately when minting
// GitHub App installation access tokens.
if IsGitHubAppOnlyScope(scope) {
continue
}
… and GitHubAppPermissionsConfig

Respond to code review feedback: use two separate embedded types to clearly
separate GitHub Actions GITHUB_TOKEN scopes from GitHub App-only scopes.
PermissionsConfig now embeds both, preserving all existing field access patterns.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan
Copy link
Contributor

@copilot keep working

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan
Copy link
Contributor

@copilot Keep working

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan
Copy link
Contributor

@copilot keep working

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 18, 2026

@copilot keep working

All four review issues are now addressed in commit 0e3885f:

  • GetExplicit() added to Permissions — returns only explicitly-declared scopes, never shorthand-derived values
  • Validation (github_app_permissions_validation.go) uses GetExplicit() so read-all/write-all shorthand never incorrectly triggers "GitHub App required"
  • App token fields (convertPermissionsToAppTokenFields) uses GetExplicit() for all App-only scopes so shorthand doesn't accidentally emit broad App permissions
  • RenderToYAML() now returns "" (not a bare permissions: header) when all scopes are skipped
  • organization-projects moved under the // GitHub App-only comment block in convertStringToPermissionScope
  • Added test cases for read-all/write-all/all: read shorthand not requiring a GitHub App, and for only-App-only scopes rendering to empty string

@pelikhan
Copy link
Contributor

@copilot remove secrets related permissions, like organization secrets, dependabot secrets, ...

Show full list of permissions.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 18, 2026

@copilot remove secrets related permissions, like organization secrets, dependabot secrets, ...

Show full list of permissions.

Done in 74c7101. Removed secrets, dependabot-secrets, organization-secrets, and codespaces-secrets from the GitHub App-only list across all four files.

Full remaining GitHub App-only permission scopes:

Repository-level:
administration, environments, git-signing, vulnerability-alerts, workflows, repository-hooks, single-file, codespaces, repository-custom-properties

Organization-level:
organization-projects, members, organization-administration, team-discussions, organization-hooks, organization-members, organization-packages, organization-self-hosted-runners, organization-custom-org-roles, organization-custom-properties, organization-custom-repository-roles, organization-announcement-banners, organization-events, organization-plan, organization-user-blocking, organization-personal-access-token-requests, organization-personal-access-tokens, organization-copilot, organization-codespaces

User-level:
email-addresses, codespaces-lifecycle-admin, codespaces-metadata

@pelikhan
Copy link
Contributor

@copilot ensure that write permissions are properly flagged and refused.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 18, 2026

@copilot ensure that write permissions are properly flagged and refused.

Done in 35dfe24. Added compile-time validation that refuses write for the GitHub App-only scopes that only support read:

  • organization-events
  • organization-plan
  • email-addresses
  • codespaces-metadata

Attempting to set any of these to write now produces:

The following GitHub App permissions are read-only and do not support "write" access:

  - organization-events

Change the permission level to "read" or remove these permissions.

All other GitHub App-only scopes (e.g., administration, members, workflows) continue to accept both read and write.

@pelikhan
Copy link
Contributor

@copilot refuse all write permissions always. Writes are done through safe outputs.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 18, 2026

@copilot refuse all write permissions always. Writes are done through safe outputs.

Done in 8e64e40. All write permissions are now refused for every GitHub App-only scope. The error message directs users to safe-outputs for write operations:

GitHub App permissions must be declared as "read" only.
Write operations are performed via safe-outputs, not through declared permissions.
The following GitHub App-only permissions were declared with "write" access:

  - administration

Change the permission level to "read" or use safe-outputs for write operations.

Removed the intermediate GetReadOnlyGitHubAppOnlyScopes()/IsReadOnlyGitHubAppOnlyScope() helpers since the distinction is no longer meaningful.

@pelikhan
Copy link
Contributor

@copilot use the technical-doc-writer agent to update the docs

Add a new '### GitHub App-Only Permissions' section to the permissions
reference documenting scopes that cannot be set on GITHUB_TOKEN. These
scopes are omitted from the compiled permissions block and forwarded to
actions/create-github-app-token when a GitHub App is configured.

Cover: full scope list by level, read-only constraint, github-app
configuration requirement, and shorthand exemption.

Also update the Write Permission Policy exceptions list to mention that
GitHub App-only scopes always refuse write at compile time.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 18, 2026

@copilot use the technical-doc-writer agent to update the docs

Done in 310f2c9. Updated docs/src/content/docs/reference/permissions.md with a new ### GitHub App-Only Permissions section covering:

  • Full list of 31 scopes organized by repository, organization, and user level
  • Scopes are omitted from compiled permissions: YAML and forwarded to actions/create-github-app-token
  • write is always a compile error; safe-outputs is required for write operations
  • A missing github-app config causes a compile error (shorthand permissions exempt)
  • Minimal aw code example

Also updated the Write Permission Policy exceptions list to include the GitHub App-only scope restriction.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh gh auth status (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@pelikhan pelikhan merged commit 998805e into main Mar 18, 2026
82 checks passed
@pelikhan pelikhan deleted the copilot/add-support-for-github-app-permissions branch March 18, 2026 12:08
lpcox added a commit that referenced this pull request Mar 18, 2026
* docs: add GH_HOST and RUNNER_TEMP to glossary (daily scan 2026-03-18) (#21553)

* docs: update GHES CLI docs and add Copilot GHES troubleshooting guide (#21528)

* Fix list height not updating on terminal resize (#21555)

* fix(daily-workflow-updater): unblock PR creation by setting protected-files: allowed (#21554)

* chore: bump MCP Gateway v0.1.15→v0.1.17 (#21552)

* feat: custom Huh theme mapped from pkg/styles Dracula palette (#21557)

* Add top-level `github-app` frontmatter as universal fallback for token minting (#21510)

* feat: add GitHub App-only permissions support (#21511)

* fix: fall back to existing remote tracking ref when incremental patch fetch fails (#21568)

* Add weekly blog post writer agentic workflow (#21575)

* ci: add timeout-minutes to all 25 jobs lacking explicit limits (#21601)

* fix: add setupGlobals in generate_aw_info step to fix staged mode ReferenceError (#21602)

* Disable lockdown mode for weekly blog post generator (#21598)

* fix: replace git push with GraphQL signed commits to satisfy required_signatures rulesets (#21576)

* docs: add weekly update blog post for 2026-03-18 (#21608)

Covers v0.58.0 through v0.61.0 (7 releases this week),
notable PRs, and auto-triage-issues as Agent of the Week.

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix failing CI: merge main to include setupGlobals in generate_aw_info step and update golden files

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
lpcox added a commit that referenced this pull request Mar 18, 2026
…ains on data residency (#21527)

* Initial plan

* Fix threat detection AWF run missing --copilot-api-target and GHE domains on data residency

When engine.api-target is configured for GHE Cloud with data residency,
propagate the APITarget from the main engine config to the detection
engine config so the threat detection AWF invocation receives the same
--copilot-api-target flag and GHE-specific domains in --allow-domains.

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Add GITHUB_COPILOT_BASE_URL env var support and fix integration test api-target

- Fix TestAPITargetDomainsInThreatDetectionStep to use api.contoso-aw.ghe.com
  (copilot-api. prefix does not trigger base-domain derivation in GetAPITargetDomains)
- Add GetCopilotAPITarget() helper: resolves --copilot-api-target from engine.api-target
  (explicit) or GITHUB_COPILOT_BASE_URL in engine.env (fallback), mirroring the
  OPENAI_BASE_URL/ANTHROPIC_BASE_URL pattern for Codex/Claude
- Update awf_helpers.go, copilot_engine_execution.go, and domains.go to use the helper
- Add unit tests for GetCopilotAPITarget and engine execution step
- Add integration test TestGitHubCopilotBaseURLInCompiledWorkflow
- Update engines.md docs to document GITHUB_COPILOT_BASE_URL

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

* Update DefaultMCPGatewayVersion to v0.1.17 and regenerate golden/lock files (#21609)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

* fix: merge main to resolve failing build-wasm and test CI jobs (#21612)

* docs: add GH_HOST and RUNNER_TEMP to glossary (daily scan 2026-03-18) (#21553)

* docs: update GHES CLI docs and add Copilot GHES troubleshooting guide (#21528)

* Fix list height not updating on terminal resize (#21555)

* fix(daily-workflow-updater): unblock PR creation by setting protected-files: allowed (#21554)

* chore: bump MCP Gateway v0.1.15→v0.1.17 (#21552)

* feat: custom Huh theme mapped from pkg/styles Dracula palette (#21557)

* Add top-level `github-app` frontmatter as universal fallback for token minting (#21510)

* feat: add GitHub App-only permissions support (#21511)

* fix: fall back to existing remote tracking ref when incremental patch fetch fails (#21568)

* Add weekly blog post writer agentic workflow (#21575)

* ci: add timeout-minutes to all 25 jobs lacking explicit limits (#21601)

* fix: add setupGlobals in generate_aw_info step to fix staged mode ReferenceError (#21602)

* Disable lockdown mode for weekly blog post generator (#21598)

* fix: replace git push with GraphQL signed commits to satisfy required_signatures rulesets (#21576)

* docs: add weekly update blog post for 2026-03-18 (#21608)

Covers v0.58.0 through v0.61.0 (7 releases this week),
notable PRs, and auto-triage-issues as Agent of the Week.

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix failing CI: merge main to include setupGlobals in generate_aw_info step and update golden files

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Co-authored-by: Landon Cox <landon.cox@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

3 participants