fix(push-protection): use alerts API proxy when security_and_analysis is unreadable#224
fix(push-protection): use alerts API proxy when security_and_analysis is unreadable#224don-petry wants to merge 39 commits into
Conversation
|
PR is ready for review. All checks passing (SonarCloud quality gate passed, ShellCheck clean, AgentShield passed). CodeQL is still running but expected to pass since the changes are pure shell additions with no new code patterns. Tagging @petry-projects/org-leads for review per CODEOWNERS. |
|
Warning Review limit reached
More reviews will be available in 59 minutes and 46 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR updates push-protection audit and apply logic to gracefully degrade when the OAuth token cannot read repository-level ChangesGraceful Degradation for Unreadable Repository Security Analysis
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR addresses recurring push-protection compliance findings when the audit token cannot read security_and_analysis from GET /repos/{owner}/{repo} by adding a proxy verification path via the secret-scanning alerts API, and updating the standard to document the token-scope behavior.
Changes:
- Add a fallback in
pp_check_security_and_analysisthat uses the secret-scanning alerts API to distinguish “unavailable” from “unverifiable.” - Make
pp_apply_security_and_analysiscontinue applying required settings even when the currentsecurity_and_analysisstate can’t be read. - Document the token-scope requirement and fallback behavior in the push-protection standard.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| standards/push-protection.md | Documents why security_and_analysis may be unreadable and how the audit falls back to proxy verification. |
| scripts/lib/push-protection.sh | Implements proxy-check fallback via secret-scanning alerts and makes apply logic proceed when state is unreadable. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ok "$ORG/$repo security_and_analysis updated successfully" | ||
| else | ||
| err "Failed to PATCH security_and_analysis for $ORG/$repo — check admin scope and that the org plan supports these features" | ||
| err "Failed to PATCH security_and_analysis for $ORG/$repo — token requires admin or \`security_events\` OAuth scope, and the org plan must support these features" |
| # Remaining settings (push_protection, ai_detection, non_provider_patterns, | ||
| # dependabot_security_updates) cannot be individually verified without | ||
| # admin / security_events scope; report as partially unverifiable so the | ||
| # finding reflects the actual state of knowledge. | ||
| add_finding "$repo" "push-protection" "security_and_analysis_unverifiable" "warning" \ | ||
| "Secret scanning is active but push_protection, ai_detection, non_provider_patterns, and dependabot_security_updates cannot be individually verified — the audit token lacks admin or \`security_events\` OAuth scope. To fully verify or enforce all settings: (1) add \`security_events\` scope to \`ORG_SCORECARD_TOKEN\`, or (2) run \`scripts/apply-repo-settings.sh $repo\` with an admin token." \ |
| **To enable full verification:** add the `security_events` OAuth scope to | ||
| `ORG_SCORECARD_TOKEN` in org Settings → Secrets, or run | ||
| `scripts/apply-repo-settings.sh <repo>` with an admin token to configure all | ||
| required settings and grant the audit token visibility. | ||
|
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/lib/push-protection.sh`:
- Around line 137-145: The current comment above the alerts_response / gh_api
call incorrectly states the secret-scanning alerts endpoint is accessible
without admin scope on public repos; update that comment to clarify that the
endpoint requires the authenticated user to be an administrator of the
repository or owning organization regardless of public/private visibility, and
that scope substitution (e.g., using public_repo vs repo) does not remove the
admin role requirement; also note the intended use of this proxy is for cases
where the caller is an admin who has a token with the security_events scope but
not the full repo scope, so the proxy can succeed when security_and_analysis
checks would fail due to scope differences (referencing alerts_response, gh_api,
ORG and repo in the surrounding code).
- Around line 117-122: Update the error message and surrounding comment in
scripts/lib/push-protection.sh: change the err call that currently mentions
`security_events` so it only states that the PATCH to update
`security_and_analysis` failed because the authenticated token/user must have
admin permissions on the repository (remove any suggestion that adding
`security_events` OAuth scope will allow the PATCH). Also correct the comment
that describes the secret-scanning alerts proxy check (the block referencing
access for public repos) to remove the incorrect claim that public repositories
bypass the admin requirement—note that the secret-scanning alerts endpoint
requires repository admin privileges regardless of visibility; keep the proxy
check logic but update its comment to reflect the admin requirement.
In `@standards/push-protection.md`:
- Around line 441-444: Update the remediation paragraph under "To enable full
verification" to instruct owners to regenerate or rotate the classic personal
access token (PAT) in Developer Settings → Personal access tokens (classic) with
the security_events scope checked, then update the ORG_SCORECARD_TOKEN value in
org Settings → Secrets; also keep the alternative command reference to
scripts/apply-repo-settings.sh <repo> using an admin token to configure required
settings and grant the audit token visibility. Ensure the text explicitly names
the security_events scope and the ORG_SCORECARD_TOKEN secret so maintainers know
to change the PAT in Developer Settings before updating the secret.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0e90f2fe-942c-4bc3-b4dc-4f4711379bd8
📒 Files selected for processing (2)
scripts/lib/push-protection.shstandards/push-protection.md
| if echo "$full_payload" | gh api -X PATCH "repos/$ORG/$repo" --input - > /dev/null 2>&1; then | ||
| ok "$ORG/$repo security_and_analysis updated successfully" | ||
| else | ||
| err "Failed to PATCH security_and_analysis for $ORG/$repo — check admin scope and that the org plan supports these features" | ||
| err "Failed to PATCH security_and_analysis for $ORG/$repo — token requires admin or \`security_events\` OAuth scope, and the org plan must support these features" | ||
| return 1 | ||
| fi |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
GitHub REST API PATCH /repos/{owner}/{repo} scope requirements security_and_analysis
💡 Result:
For PATCH /repos/{owner}/{repo} when using the security_and_analysis field, GitHub requires the caller to have admin permissions for the repository OR to be an organization owner or a security manager for the organization that owns the repository. [1] Practical notes (authentication/authorization): - The endpoint is “Update a repository” (PATCH /repos/{owner}/{repo}). [1] - The security_and_analysis parameter specifically controls enabling/disabling security and analysis features for the repository. [1] - GitHub also states that to use security_and_analysis you must have the permissions described above (repo admin OR org owner/security manager). [1] If you’re asking what OAuth scope / PAT scope corresponds to this: the REST endpoint docs for PATCH /repos/{owner}/{repo} describe the required permissions in terms of GitHub roles (admin/owner/security manager), not a specific OAuth scope string. GitHub’s general guidance is to use tokens with the “required scopes or permissions,” and that endpoint references state what’s required. [2][3]
Citations:
- 1: https://docs.github.com/rest/repos/repos
- 2: https://docs.github.com/en/rest/authentication/authenticating-to-the-rest-api?apiVersion=2026-03-10
- 3: https://docs.github.com/en/rest/using-the-rest-api/getting-started-with-the-rest-api?apiVersion=2026-03-10
🌐 Web query:
GitHub REST API security_events OAuth scope permissions
💡 Result:
The security_events OAuth scope for GitHub REST API grants read and write access to security events in the code scanning API.[1][2][3] It is required for OAuth app tokens and personal access tokens (classic) to access code scanning endpoints (e.g., listing, getting, updating alerts) on private or public repositories.[3][4] For public repositories only, public_repo scope suffices.[3] This scope allows access to security events without granting broader code access (e.g., unlike repo scope).[1] It also appears in OAuth authorization objects as security_events with read or write enum values.[5] For GitHub Apps, corresponding security_events read/write permissions are needed.[4]
Citations:
- 1: https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps
- 2: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps
- 3: https://docs.github.com/rest/code-scanning/code-scanning
- 4: https://docs.github.com/en/enterprise-server@3.4/rest/code-scanning
- 5: https://docs.github.com/en/rest/apps/oauth-applications
🏁 Script executed:
cat -n scripts/lib/push-protection.sh | sed -n '70,170p'Repository: petry-projects/.github
Length of output: 5925
🌐 Web query:
GitHub REST API secret-scanning alerts GET endpoint public repository admin scope requirement
💡 Result:
For the GitHub REST API endpoint GET /repos/{owner}/{repo}/secret-scanning/alerts (List secret scanning alerts for a repository): 1) Admin scope requirement (who can call) The authenticated user must be an administrator for the repository, or for the organization that owns the repository, to use this endpoint. [1] 2) OAuth/PAT scopes (what token scope is needed) - OAuth app tokens and classic personal access tokens (PATs) need the repo or security_events scope to use this endpoint. [1] - If the endpoint is used only with public repositories, the token can instead use the public_repo scope. [1] 3) Notes for GitHub Enterprise Server The same admin and token-scope requirements are also stated for GitHub Enterprise Server for this endpoint. [2] Answering your query directly: yes, this endpoint requires repository/org administrator privileges (admin requirement) and requires repo or security_events scope (or public_repo when restricted to public repositories). [1][2]
Citations:
- 1: https://docs.github.com/rest/secret-scanning/secret-scanning
- 2: https://docs.github.com/en/enterprise-server@3.17/rest/secret-scanning/secret-scanning
🌐 Web query:
GitHub OAuth scope repo versus security_events PATCH repository settings
💡 Result:
repo vs security_events scopes (GitHub OAuth) and how they relate to PATCH repository settings 1) OAuth scope repo vs security_events - repo grants full access to public and private repositories, including read/write access to code and many repo-related capabilities (e.g., invitations, collaborators, deployment statuses, repository webhooks, plus some org-owned resources like projects/invitations/team memberships/webhooks). [1] - security_events grants read and write access to security events in GitHub’s code scanning API (and is described as only necessary to access security events without granting access to the code). [1] 2) OAuth scope needed to PATCH repository settings (including security_and_analysis) - For the REST API endpoint PATCH /repos/{owner}/{repo} (used to update repository settings, including security_and_analysis), the docs specify that you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. [2][3] - The repo vs security_events OAuth scopes are not called out as the gating factor for this PATCH endpoint in the docs; instead the authorization requirement is based on repository/organization permissions (admin/owner/security manager). [2][3] 3) Practical takeaway - Use security_events when you only need to read/write security event data (e.g., code scanning/secret scanning events) without needing broad code/repository access. [1] - If your integration needs to change repository “security and analysis” settings via PATCH /repos/{owner}/{repo} (the settings side), you should not assume security_events is sufficient; the API’s requirement is admin/owner/security-manager authorization, regardless of whether you requested repo or security_events. [2][3] If you tell me whether you’re targeting GitHub.com vs GitHub Enterprise Server/Cloud, and exactly which PATCH you mean (repository-level PATCH /repos/{owner}/{repo} vs enterprise-level security config endpoints), I can map the required OAuth scopes/permissions more precisely to that specific endpoint.
Citations:
- 1: https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps
- 2: https://docs.github.com/rest/repos/repos
- 3: https://docs.github.com/en/rest/repos/repos?apiVersion=2026-03-10
Line 120 error message misleads about security_events scope and PATCH requirements.
The error message at line 120 incorrectly suggests that security_events OAuth scope can fix a PATCH failure. Per GitHub REST API documentation, security_events scope grants read/write access to code scanning and secret scanning alerts only, not to repository settings like security_and_analysis. PATCH /repos/{owner}/{repo} requires admin permissions on the repository; security_events alone cannot fulfill this requirement. A maintainer adding security_events to their token after seeing this error will retry and encounter the same failure.
Additionally, the comment at lines 137–141 is inaccurate. It claims the secret-scanning alerts endpoint is "accessible without admin scope on public repositories," but GitHub REST API documentation states that this endpoint requires the authenticated user to be an administrator for the repository, regardless of visibility (public or private). The endpoint is used as a proxy check in the code, but the admin requirement still applies.
Recommended fixes:
- Line 120: Remove mention of
security_eventsscope; clarify that the caller must have admin permissions on the repository. - Lines 137–141: Remove the claim about public repos bypassing the admin requirement; the proxy check still requires admin authentication.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/lib/push-protection.sh` around lines 117 - 122, Update the error
message and surrounding comment in scripts/lib/push-protection.sh: change the
err call that currently mentions `security_events` so it only states that the
PATCH to update `security_and_analysis` failed because the authenticated
token/user must have admin permissions on the repository (remove any suggestion
that adding `security_events` OAuth scope will allow the PATCH). Also correct
the comment that describes the secret-scanning alerts proxy check (the block
referencing access for public repos) to remove the incorrect claim that public
repositories bypass the admin requirement—note that the secret-scanning alerts
endpoint requires repository admin privileges regardless of visibility; keep the
proxy check logic but update its comment to reflect the admin requirement.
| **To enable full verification:** add the `security_events` OAuth scope to | ||
| `ORG_SCORECARD_TOKEN` in org Settings → Secrets, or run | ||
| `scripts/apply-repo-settings.sh <repo>` with an admin token to configure all | ||
| required settings and grant the audit token visibility. |
There was a problem hiding this comment.
Remediation step references the wrong UI location.
OAuth scopes can't be added from "org Settings → Secrets" — that page only stores the secret's value for use in workflow runs. To grant security_events, the owner of ORG_SCORECARD_TOKEN must regenerate (or rotate) the underlying classic PAT in Developer Settings → Personal access tokens (classic) with the new scope checked, then update the value stored in org Settings → Secrets. As written, a maintainer following these instructions will land in the secrets page and find no way to change scopes.
📝 Suggested rewording
-**To enable full verification:** add the `security_events` OAuth scope to
-`ORG_SCORECARD_TOKEN` in org Settings → Secrets, or run
-`scripts/apply-repo-settings.sh <repo>` with an admin token to configure all
-required settings and grant the audit token visibility.
+**To enable full verification:** regenerate the classic PAT backing
+`ORG_SCORECARD_TOKEN` (Developer Settings → Personal access tokens) with the
+`security_events` scope, then update the value stored in org Settings →
+Secrets → Actions. Alternatively, run `scripts/apply-repo-settings.sh <repo>`
+with an admin token to configure all required settings and grant the audit
+token visibility.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| **To enable full verification:** add the `security_events` OAuth scope to | |
| `ORG_SCORECARD_TOKEN` in org Settings → Secrets, or run | |
| `scripts/apply-repo-settings.sh <repo>` with an admin token to configure all | |
| required settings and grant the audit token visibility. | |
| **To enable full verification:** regenerate the classic PAT backing | |
| `ORG_SCORECARD_TOKEN` (Developer Settings → Personal access tokens) with the | |
| `security_events` scope, then update the value stored in org Settings → | |
| Secrets → Actions. Alternatively, run `scripts/apply-repo-settings.sh <repo>` | |
| with an admin token to configure all required settings and grant the audit | |
| token visibility. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@standards/push-protection.md` around lines 441 - 444, Update the remediation
paragraph under "To enable full verification" to instruct owners to regenerate
or rotate the classic personal access token (PAT) in Developer Settings →
Personal access tokens (classic) with the security_events scope checked, then
update the ORG_SCORECARD_TOKEN value in org Settings → Secrets; also keep the
alternative command reference to scripts/apply-repo-settings.sh <repo> using an
admin token to configure required settings and grant the audit token visibility.
Ensure the text explicitly names the security_events scope and the
ORG_SCORECARD_TOKEN secret so maintainers know to change the PAT in Developer
Settings before updating the secret.
|
Auto-rebase failed — merge conflict — this branch has conflicts with Please resolve the conflicts and push: |
… is unreadable
The compliance audit token (ORG_SCORECARD_TOKEN) lacks the admin or
`security_events` OAuth scope needed to read the `security_and_analysis`
field from GET /repos/{owner}/{repo}. This caused the audit to emit
`security_and_analysis_unavailable` every week with no actionable path
to resolution, since the token also couldn't verify whether the settings
were actually configured.
Changes to scripts/lib/push-protection.sh:
- pp_check_security_and_analysis: when security_and_analysis is unreadable,
fall back to a proxy check via the secret-scanning alerts endpoint
(accessible without admin scope on public repos). If the alerts endpoint
returns a valid array, secret scanning is confirmed active and the finding
is emitted as `security_and_analysis_unverifiable` (more accurate) instead
of `security_and_analysis_unavailable`. Both findings include actionable
guidance: add `security_events` scope to ORG_SCORECARD_TOKEN, or run
apply-repo-settings.sh with an admin token.
- pp_apply_security_and_analysis: remove the premature return 1 when the
current state is unreadable. The loop already handles null/missing values
correctly (treating them as needing update), so the apply now proceeds
unconditionally when the state is unreadable — all required values are
"enabled" so this is idempotent. Improves the error message to mention
both admin scope and security_events scope.
Changes to standards/push-protection.md:
- Document the token scope requirement for full security_and_analysis
verification and explain the proxy-check fallback behavior introduced
by this fix.
Closes #117
Co-authored-by: Don Petry <don-petry@users.noreply.github.com>
0e723e2 to
4a39ef6
Compare
Superseded by automated re-review at
|
Superseded by automated re-review at
|
|
@dev-lead - please fix this PR |
|



Summary
security_and_analysis_unavailablecompliance finding (Compliance: security_and_analysis_unavailable #117) by introducing a proxy check via the secret-scanning alerts API when the primarysecurity_and_analysisfield is unreadable.pp_apply_security_and_analysismore robust when the current settings state cannot be read.standards/push-protection.md.Root Cause
The audit token (
ORG_SCORECARD_TOKEN) lacksadminorsecurity_eventsOAuth scope, soGET /repos/{owner}/{repo}returnssecurity_and_analysis: null. The check treated null the same as "unavailable," firingsecurity_and_analysis_unavailableevery week with no self-resolving path.Changes
scripts/lib/push-protection.shpp_check_security_and_analysis: Whensecurity_and_analysisis unreadable, falls back toGET /repos/{owner}/{repo}/secret-scanning/alerts(accessible without admin scope on public repos):security_and_analysis_unverifiable(accurate, actionable) instead ofsecurity_and_analysis_unavailable. This causes issue Compliance: security_and_analysis_unavailable #117 to auto-close on the next audit run.security_and_analysis_unavailablewith improved guidance mentioningsecurity_eventsscope and the apply script.pp_apply_security_and_analysis: Removes the prematurereturn 1when current state is unreadable. The loop already handles null/missing values correctly (all required values are"enabled", so applying unconditionally is idempotent and safe).standards/push-protection.mdsecurity_eventsscope requirement and the proxy-check fallback behaviour.Test plan
security_and_analysis_unavailableis no longer in findings for.github)security_and_analysis_unverifiablefinding is created with actionable remediation stepsapply-repo-settings.shno longer exits early whensecurity_and_analysisis unreadable — it attempts to apply all settings and reports success or a clear errorCloses #117
Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Documentation