Skip to content

fix(security): Remove unsafe PR head checkout in pull_request_target workflow#790

Closed
fix-it-felix-sentry[bot] wants to merge 1 commit intomasterfrom
security/fix-pull-request-target-vuln
Closed

fix(security): Remove unsafe PR head checkout in pull_request_target workflow#790
fix-it-felix-sentry[bot] wants to merge 1 commit intomasterfrom
security/fix-pull-request-target-vuln

Conversation

@fix-it-felix-sentry
Copy link
Copy Markdown

Summary

This PR fixes a high-severity security vulnerability (VULN-1416) in the changelog-preview workflow where untrusted PR code could be executed with access to repository secrets.

Problem

The workflow uses pull_request_target which runs with elevated permissions and access to secrets. The vulnerable code had a fallback that would checkout the PR head ref (github.event.pull_request.head.sha) when merge conflicts existed:

- uses: actions/checkout@v6
  if: steps.checkout-merge.outcome == 'failure'
  with:
    ref: ${{ github.event.pull_request.head.sha }}  # ⚠️ UNSAFE

This allowed attackers to potentially execute arbitrary code from malicious PRs with full repository access.

Solution

  • ✅ Removed the unsafe fallback checkout of PR head
  • ✅ Workflow now fails safely when merge conflicts exist
  • ✅ Added clear error messages instructing users to resolve conflicts
  • ✅ Updated security documentation in the workflow file

Changes

  1. Removed continue-on-error: true from merge ref checkout
  2. Removed the fallback checkout step entirely
  3. Added a failure handler with informative error messages
  4. Enhanced security notes to document the safeguards

Testing

This is a workflow configuration change. The behavior change is:

  • Before: Workflow would checkout PR head when merge conflicts existed
  • After: Workflow fails gracefully with clear error message

No existing tests are affected as there are no automated tests for workflow files.

References

…workflow

This commit addresses a high-severity security vulnerability where the
workflow would fall back to checking out the PR head when merge conflicts
existed. With pull_request_target, checking out untrusted PR code could
allow attackers to execute arbitrary code with access to repository secrets.

Changes:
- Removed the fallback checkout step that used github.event.pull_request.head.sha
- Removed continue-on-error from the merge ref checkout
- Added a failure handler that provides clear error messages when merge conflicts exist
- Updated security notes to document the safeguards

The workflow now fails safely when merge conflicts are present, requiring
them to be resolved before the changelog preview can run.

Fixes: https://linear.app/getsentry/issue/DI-1825
Related: https://linear.app/getsentry/issue/VULN-1416

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Comment on lines +96 to +101
- name: Check for merge conflicts
if: failure()
run: |
echo "::error::Unable to checkout merge ref. This PR likely has merge conflicts."
echo "::error::Please resolve merge conflicts before the changelog preview can be generated."
exit 1
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: The error handling step with if: failure() will not execute when the checkout-merge step fails because continue-on-error: true was removed from the failing step.
Severity: MEDIUM

Suggested Fix

Reinstate continue-on-error: true on the checkout-merge step. This will allow the workflow to proceed to the next step, where the if: failure() condition can be evaluated to display the intended error message when merge conflicts occur.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: .github/workflows/changelog-preview.yml#L96-L101

Potential issue: The `checkout-merge` step had `continue-on-error: true` removed, and a
new step with `if: failure()` was added to handle checkout failures. However, GitHub
Actions jobs halt immediately on a failed step. Subsequent steps, even those with an
`if: failure()` condition, are not evaluated unless the failing step is marked with
`continue-on-error: true`. Consequently, if the `checkout-merge` step fails (e.g., due
to merge conflicts), the intended error message will not be displayed, and the workflow
will fail without providing the helpful context to the user.

Did we get this right? 👍 / 👎 to inform future reviews.

@BYK
Copy link
Copy Markdown
Member

BYK commented Apr 8, 2026

This is intentional

@BYK BYK closed this Apr 8, 2026
@BYK BYK deleted the security/fix-pull-request-target-vuln branch April 8, 2026 09:22
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.

1 participant