Skip to content

Honor bot allowlists before confused-deputy checks - #60135

Merged
pelikhan merged 23 commits into
mainfrom
copilot/fix-confused-deputy-check
Sep 11, 2026
Merged

Honor bot allowlists before confused-deputy checks#60135
pelikhan merged 23 commits into
mainfrom
copilot/fix-confused-deputy-check

Conversation

Copilot AI commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Allowlisted bots were rejected on pull request synchronize events when pushing to PRs opened by another actor. The confused-deputy check ran before the explicit on.bots authorization.

  • Authorization

    • Check the bot allowlist and repository installation status first.
    • Authorize active trusted bots.
    • Continue denying unlisted or inactive bots.
  • Coverage

    • Cover both pull_request and pull_request_target synchronization.
    • Verify inactive allowlisted bots fail closed.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • github.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "github.com"

See Network Configuration for more information.

Generated by 👨‍🍳 PR Sous Chef · pi · gpt54 · 15.7 AIC · ⊞ 8.9K ·
Comment /souschef to run again


Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • github.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "github.com"

See Network Configuration for more information.

Generated by 👨‍🍳 PR Sous Chef · pi · gpt54 · 28.9 AIC · ⊞ 9.3K ·
Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · pi · gpt54 · 16.3 AIC · ⊞ 8.9K ·
Comment /souschef to run again

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix confused-deputy check to consult allowlist for bot actors Honor bot allowlists before confused-deputy checks Sep 11, 2026
Copilot AI requested a review from pelikhan September 11, 2026 01:38
@pelikhan
pelikhan marked this pull request as ready for review September 11, 2026 02:19
Copilot AI balanced review requested due to automatic review settings September 11, 2026 02:19
@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Ponytail Reviewer completed successfully!

Lean already. Ship.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • ab.chatgpt.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "ab.chatgpt.com"

See Network Configuration for more information.

Generated by Ponytail Reviewer for #60135

@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • registry.npmjs.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "registry.npmjs.org"

See Network Configuration for more information.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

⚠️ PR Code Quality Reviewer failed during code quality review.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • github.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "github.com"

See Network Configuration for more information.

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

⚠️ Security scanning failed for Design Decision Gate 🏗️. Review the logs for details.

No ADR enforcement needed: PR does not have the 'implementation' label and has ≤100 new lines of code in business logic directories.

🏗️ ADR gate enforced by Design Decision Gate 🏗️

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The reordering lets allowlisted bots bypass confused-deputy protection on unrelated event types.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Updates bot authorization ordering so trusted active bots can synchronize pull requests opened by other actors.

Changes:

  • Checks bot allowlists before PR confused-deputy validation.
  • Adds synchronization and inactive-bot regression tests.
File summaries
File Description
actions/setup/js/check_membership.cjs Reorders bot authorization and confused-deputy checks.
actions/setup/js/check_membership.test.cjs Covers both PR synchronization event types and inactive bots.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread actions/setup/js/check_membership.cjs Outdated
@github-actions

Copy link
Copy Markdown
Contributor

Test Quality Sentinel Report 🧪

PR Context


Test Quality Score: 100/100 ✅ Excellent

Test Coverage Summary

Test Case Type Assertions Coverage Quality
"should authorize an active allowlisted bot when actor differs from PR author (pull_request/pull_request_target synchronize)" parametrized (2 scenarios) 4 bot allowlist bypass, confused-deputy skip, event type coverage HIGH - design invariant
"should deny an inactive allowlisted bot when actor differs from PR author" error path 3 bot denial, inactive bot handling, confused-deputy guard HIGH - defense-in-depth

Quality Analysis

Test 1: Active Allowlisted Bot Authorization

  • Uses it.each(["pull_request", "pull_request_target"]) parametrization ✓
  • Verifies bot allowlist is checked BEFORE confused-deputy logic
  • Confirms both PR synchronize event types are properly authorized
  • Mocks GitHub API collaborator permission check (external I/O)
  • Assertions validate: is_team_member=true, result=authorized_bot, result≠confused_deputy

Test 2: Inactive Allowlisted Bot Denial

  • Tests defense-in-depth: allowlisted but inactive → bot_not_active
  • Mocks 404 error response from GitHub API (bot not installed)
  • Confirms confused-deputy does NOT trigger for allowlisted bots
  • Critical security guarantee: allowlist check is gating, not bypassing safety checks

Coverage Highlights

  • ✓ Both happy path (authorized) and error path (not active) tested
  • ✓ Parametrized tests credit both event types as separate scenarios
  • ✓ External API mocks only (no internal call assertions)
  • ✓ All assertions are behavioral (observable results, not implementation details)
  • ✓ No test inflation violations (28:10 ratio is acceptable for security-critical fix)

No Red Flags

  • ✓ No Go mock libraries (JavaScript/vitest only)
  • ✓ No internal-only mocks (API mocking is appropriate)
  • ✓ No assertion-message gaps (all expect() calls are clear)
  • ✓ No duplicated test patterns (2 focused, unique scenarios)

Scoring Breakdown

  • Design Tests: 2/2 (100%) → 40 points
  • Edge/Error Coverage: 2/2 (100%) → 30 points
  • Duplication Check: 0 clusters → 20 points
  • Test Inflation Ratio: 2.8:1 (acceptable for security work) → 10 points

Total: 100/100


What This PR Tests

This PR adds critical test coverage for the bot allowlist authorization check ordering fix (Issue #59952). The tests verify that:

  1. Allowlist acts as a primary gate: Bots in on.bots: are authorized immediately without role checks.
  2. Security is layered: Even allowlisted bots are denied if not installed (bot_not_active).
  3. Confused-deputy check is bypassed only for authorized bots: Active allowlisted bots skip the confused-deputy attack detection, preventing legitimate bot synchronize events from being falsely rejected.
  4. Both PR event types work: Tests cover both pull_request and pull_request_target synchronize events.

Approval ✅

Implementation tests: 0%
Design tests: 100%
Violations: None

All tests are behavioral design tests covering critical security authorization logic. The test inflation ratio is within acceptable bounds for security-critical changes. No coding guideline violations.

Recommendation: Approve — Test quality is excellent and properly validates the security fix.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • github.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "github.com"

See Network Configuration for more information.

🧪 Test quality analysis by Test Quality Sentinel · copilot · haiku45 · 22.9 AIC · ⌖ 17 AIC · ⊞ 8.4K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 100/100. 0% implementation tests (threshold: 30%). All tests are behavioral design tests covering critical security authorization logic.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Impeccable review — security/correctness pass (harden, audit modes)

This PR reorders checkBotAllowlistAuthorization to run before isConfusedDeputyAttack in check_membership.cjs, so that an allowlisted-bot match short-circuits the confused-deputy check on pull_request(_target):synchronize.

🔴 Blocking: the new ordering re-opens the exact Dependabot Confused Deputy Injection scenario ADR-29450 was written to close, for any repo whose on.bots: allowlist includes dependabot[bot] (which the project's own docs show as an example allowlist entry). See inline comment for the detailed attack trace and a suggested fix/regression test.

The added tests only cover a synthetic bot name (my-fixup-bot[bot]), so the existing suite does not catch this regression — the fix and this new test scenario should ship together.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · copilot · sonnet50 · 97.9 AIC · ⌖ 13.9 AIC · ⊞ 8.4K

Comment thread actions/setup/js/check_membership.cjs Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /diagnosing-bugs (regression risk analysis for a security-sensitive check reordering) and /tdd (test coverage gaps). Requesting changes: the fix reopens the specific attack ADR-29450 was written to close, for the actor it was designed to stop.

📋 Key Themes & Highlights

Key Themes

  • Security regression: Moving checkBotAllowlistAuthorization ahead of isConfusedDeputyAttack removes confused-deputy protection for any actor that is both allowlisted in on.bots: and installed/active on the repo — which per the project's own docs (triggers.md:291,495) commonly includes dependabot[bot] itself, the actor ADR-29450 explicitly targeted. checkBotAllowlistAuthorization/checkBotStatus only verify allowlist membership + installation status; neither checks whether the current event's actor genuinely matches the PR/comment author, so it cannot distinguish a legitimate bot-initiated event from a confused-deputy replay.
  • Test coverage gap: All new tests use a fictitious my-fixup-bot[bot] that is not simultaneously the historically-targeted actor. No test exercises the combination of "actor is dependabot[bot], is allowlisted via on.bots, and PR author differs" — which is exactly the scenario the ADR's threat model addresses and where the new ordering silently authorizes instead of denying.
  • Scope beyond synchronize: The same reordering also affects issue_comment events (the @dependabot show vector), since isConfusedDeputyAttack for issue_comment doesn't require a [bot]-suffixed actor — any allowlisted bot whose comment differs from the actor field now bypasses that check too.

Suggested Direction

Either (a) keep the confused-deputy guard ahead of the bot-allowlist bypass for actors matching known slash-command-triggerable bots (or all bots, falling back to explicit allowlist-driven override only when the actor equality also holds), or (b) if bypassing confused-deputy checks for any allowlisted bot is the intended new behavior, add explicit regression tests proving dependabot[bot] (allowlisted + active + author mismatch) is still denied, and update ADR-29450 to document the narrowed threat model and residual risk.

Positive Highlights

  • ✅ Good test hygiene: it.each used to cover both pull_request and pull_request_target for the new allowlist-first path.
  • ✅ The "inactive allowlisted bot still denied" test is a solid fail-closed check for the allowlist branch itself.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • registry.npmjs.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "registry.npmjs.org"

See Network Configuration for more information.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · 113 AIC · ⌖ 15.2 AIC · ⊞ 10.4K
Comment /matt to run again

Comment thread actions/setup/js/check_membership.cjs Outdated
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot The compact report shows a failed check on this PR. Please inspect the failing automation, address any outstanding review feedback, refresh the branch if needed, and run the pr-finisher skill before handing back to maintainers.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • github.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "github.com"

See Network Configuration for more information.

Generated by 👨‍🍳 PR Sous Chef · pi · gpt54 · 15.7 AIC · ⊞ 8.9K ·
Comment /souschef to run again

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

@copilot The compact report shows a failed check on this PR. Please inspect the failing automation, address any outstanding review feedback, refresh the branch if needed, and run the pr-finisher skill...

Addressed in d68f0f3. I inspected the failed PR Code Quality Reviewer logs (tooling failure, not a finding), incorporated all review feedback, refreshed from main, ran the pr-finisher flow, and completed full local validation.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Three unresolved review threads on this PR already have follow-up responses from the PR author or Copilot but remain unresolved:

Please resolve the remaining review state, refresh the branch if needed, and run the pr-finisher skill before handing this back to maintainers.

Run: https://github.com/github/gh-aw/actions/runs/34581583531

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • github.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "github.com"

See Network Configuration for more information.

Generated by 👨‍🍳 PR Sous Chef · pi · gpt54 · 45.9 AIC · ⊞ 9.3K ·
Comment /souschef to run again

Copilot AI and others added 2 commits September 11, 2026 09:11
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Three unresolved review threads on this PR already have follow-up responses from the PR author or Copilot but remain unresolved:

Completed the pr-finisher pass. All three named review threads are now resolved. Run 34581583531 succeeded with all 10 jobs green and no failed logs; the branch is current with main, and full local format, lint, unit, test, recompile, and pre-PR validation passed. Commit d365cf9 removed unrelated generated artifacts, leaving only the two intended membership files. The obsolete CHANGES_REQUESTED review still requires maintainer dismissal, and CI on the latest agent HEAD must be re-triggered by a maintainer.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot The obsolete blocking review still remains on this PR even though the author reports all three named threads are resolved. Please clean up the remaining review state, refresh the branch if needed, and run the pr-finisher skill before handing this back to maintainers.

Run: https://github.com/github/gh-aw/actions/runs/34589658410

Generated by 👨‍🍳 PR Sous Chef · pi · gpt54 · 42.4 AIC · ⊞ 8.9K ·
Comment /souschef to run again

Copilot AI and others added 2 commits September 11, 2026 10:44
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

@copilot The obsolete blocking review still remains on this PR even though the author reports all three named threads are resolved. Please clean up the remaining review state, refresh the branch if ne...

Completed the pr-finisher pass. Run 34589658410 succeeded with all 10 jobs green and no failed logs; all review threads are resolved, the branch is current with main, and full local format/lint/unit/test/recompile validation passed. Commit 92d998a restored the clean two-file PR diff after validation. Review 5174448175 remains the sole obsolete blocker, but this agent's available GitHub write tools do not permit dismissing reviews; a maintainer must dismiss it. CI on the latest agent HEAD also requires maintainer re-trigger.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot add logging

Copilot AI and others added 2 commits September 11, 2026 12:13
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

@copilot add logging

Added in f2a1e37. Bot synchronization authorization now logs the event, actor/PR-author relationship, same-repository result, Dependabot exclusion, and PR-author trust decision without logging secrets. The focused 57-test suite and final impacted validation pass.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot update compiler threat specification

Copilot AI and others added 2 commits September 11, 2026 12:26
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

@copilot update compiler threat specification

Updated in be72029. Compiler threat specification v1.0.34 now defines CTR-027 for allowlisted bot synchronization provenance, maps the runtime implementation and tests, assigns compliance test T-CTR-042, and documents fail-closed behavior for forks, untrusted authors, inactive bots, missing provenance, and Dependabot mismatches. Formal conformance and final impacted validation pass.

@pelikhan
pelikhan merged commit 5efc635 into main Sep 11, 2026
@pelikhan
pelikhan deleted the copilot/fix-confused-deputy-check branch September 11, 2026 12:31
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.89.5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

on.bots: allowlist is never consulted when the confused-deputy check fires on pull_request(_target):synchronize

4 participants