-
Notifications
You must be signed in to change notification settings - Fork 444
Prevent invalid id-token: read emission when merging permissions: all: read with explicit overrides
#43297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevent invalid id-token: read emission when merging permissions: all: read with explicit overrides
#43297
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -177,6 +177,10 @@ func (p *Permissions) Set(scope PermissionScope, level PermissionLevel) { | |
| // Expand all permissions to explicit permissions first | ||
| for _, s := range GetAllPermissionScopes() { | ||
| if _, exists := p.permissions[s]; !exists { | ||
| // id-token does not support the read level | ||
| if s == PermissionIdToken && p.allLevel == PermissionRead { | ||
| continue | ||
| } | ||
| p.permissions[s] = p.allLevel | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
💡 Explanation and suggested fixWhen Add the matching guard alongside the // id-token does not support the read level
if s == PermissionIdToken && p.allLevel == PermissionRead {
continue
}
// discussions: read is suppressed for GHE compatibility (only include if explicitly set)
if s == PermissionDiscussions && p.allLevel == PermissionRead {
continue
}The test added by this PR should also assert that |
||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -88,6 +88,15 @@ func TestPermissionsSet(t *testing.T) { | |
| if !exists || level != PermissionWrite { | ||
| t.Errorf("expected issues: write, got %v (exists: %v)", level, exists) | ||
| } | ||
|
|
||
| p3 := NewPermissionsAllRead() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [/tdd] The new test case is embedded flat inside 💡 Suggested refactorEither move this case into // all: read + explicit write scope must not expand id-token to any level
p3 := NewPermissionsAllRead()
p3.Set(PermissionCopilotRequests, PermissionWrite)Even better, consider adding a parallel entry in @copilot please address this. |
||
| p3.Set(PermissionCopilotRequests, PermissionWrite) | ||
| if _, exists := p3.Get(PermissionIdToken); exists { | ||
| t.Error("expected id-token to be excluded when converting all: read to explicit map") | ||
| } | ||
| if yaml := p3.RenderToYAML(); strings.Contains(yaml, "id-token: read") { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [/tdd] The YAML assertion only guards against 💡 Stronger assertionChange the assertion to check for any if yaml := p3.RenderToYAML(); strings.Contains(yaml, "id-token:") {
t.Errorf("RenderToYAML() should not contain any id-token entry, got:\n%s", yaml)
}This matches the intent of the fix — @copilot please address this. |
||
| t.Errorf("RenderToYAML() should not contain id-token: read, got:\n%s", yaml) | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test does not assert the boundary case: 💡 Suggested additional assertionAdd a case verifying the guard is not over-applied: // Guard must NOT fire at write level — id-token: write is valid
p4 := &Permissions{hasAll: true, allLevel: PermissionWrite, permissions: make(map[PermissionScope]PermissionLevel)}
p4.Set(PermissionCopilotRequests, PermissionWrite)
if level, exists := p4.Get(PermissionIdToken); !exists || level != PermissionWrite {
t.Errorf("expected id-token: write after all: write expansion, got level=%q exists=%v", level, exists)
}Without this, a future change that over-broadly guards |
||
| } | ||
|
|
||
| // TestPermissionsSetPreservesShorthandPermissions verifies that calling Set() on a Permissions | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[/diagnosing-bugs] The guard is correct and well-placed. One minor note: the comment says
id-token does not support the read level— it would be more precise to say it supports onlywriteandnone(not any non-write level), which matches how GitHub Actions actually validates permissions.💡 Suggested comment wording
This mirrors the comment in
permissions_rendering.go(if one exists) and makes the rule concrete for future readers — clarifying that this isn't a gh-aw policy but a GitHub Actions constraint.@copilot please address this.