Skip to content

chore: trigger pr on pull_request_target#44

Open
SirSimon04 wants to merge 1 commit intomainfrom
chore-protect-secrets
Open

chore: trigger pr on pull_request_target#44
SirSimon04 wants to merge 1 commit intomainfrom
chore-protect-secrets

Conversation

@SirSimon04
Copy link
Contributor

@SirSimon04 SirSimon04 commented Mar 18, 2026

Fix CI Workflow to Properly Handle pull_request_target Events

Chore

🔧 Updated CI workflow and integration test action to correctly handle pull_request_target events, ensuring PRs from external forks are checked out at the correct commit SHA and approval gating is applied consistently.

Changes

  • .github/workflows/test.yml:

    • Fixed the requires-approval condition to check head.repo.owner.login instead of base.user.login for proper fork detection.
    • Added needs: requires-approval and the corresponding if condition to both test and integration-tests jobs, ensuring they wait for approval when triggered from forks.
    • Upgraded actions/checkout from v2/v4 to v5 and actions/setup-node from v2 to v4.
    • Added explicit ref: ${{ github.event.pull_request.head.sha || github.sha }} to checkout steps to ensure the PR head commit is used (important for pull_request_target security).
  • .github/actions/integration-tests/action.yml:

    • Upgraded actions/checkout from v2 to v5 with the same explicit ref for the correct commit SHA.
    • Updated actions/setup-node from v2 to v4 and aligned node version input references to use inputs.NODE_VERSION.
  • 🔄 Regenerate and Update Summary

📬 Subscribe to the Hyperspace PR Bot DL to get the latest announcements and pilot features!

PR Bot Information

Version: 1.18.11 | 📖 Documentation | 🚨 Create Incident | 💬 Feedback

  • Event Trigger: pull_request.opened
  • Correlation ID: 79bfa020-22e6-11f1-9efe-0023cd0d2de3
  • Summary Prompt: Default Prompt
  • Output Template: Default Template
  • LLM: anthropic--claude-4.6-sonnet

@SirSimon04 SirSimon04 requested a review from a team as a code owner March 18, 2026 16:21
Copy link
Contributor

@hyperspace-insights hyperspace-insights bot left a comment

Choose a reason for hiding this comment

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

The PR introduces the correct structural pattern (pull_request_target + approval gate + pinned SHA checkout) but has a significant security gap: the approval gate is only checked once per PR and is not re-evaluated on subsequent synchronize (push) events, meaning a contributor could gain initial approval with safe code and then push malicious code. Additionally, running contributor-supplied code (npm install, tests) in the same job that holds CF secrets is inherently risky under pull_request_target. These issues should be addressed before merging.

PR Bot Information

Version: 1.18.11 | 📖 Documentation | 🚨 Create Incident | 💬 Feedback

  • LLM: anthropic--claude-4.6-sonnet
  • Event Trigger: pull_request.opened
  • Correlation ID: 79bfa020-22e6-11f1-9efe-0023cd0d2de3

Comment on lines +31 to +33
- uses: actions/checkout@v5
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
Copy link
Contributor

Choose a reason for hiding this comment

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

Security: pull_request_target with explicit ref checkout of PR head SHA is a known code injection risk

pull_request_target runs with write permissions and access to secrets, using the base repo's context for safety. Explicitly checking out github.event.pull_request.head.sha (i.e., the PR contributor's code) and then running that code (e.g., npm i, npm run test) in the same job defeats this protection — a malicious PR could modify package.json scripts or test files to exfiltrate secrets.

The requires-approval gate mitigates this for external forks (when head.repo.owner.login != 'cap-js'), but it only needs to be approved once per PR. After initial approval, subsequent pushes (synchronize event) to the same PR are not re-gated, allowing an attacker to update a seemingly-innocent PR with malicious code after the initial approval. This is a well-documented pattern (e.g., GitHub Security Lab advisory).

Consider either:

  1. Keeping secrets-consuming jobs isolated from PR head code (fetch only metadata, not run contributed code), or
  2. Using a two-workflow split: a trusted push/pull_request_target workflow that only saves artifacts, and a separate workflow_run triggered workflow that accesses secrets without running untrusted code.

Please provide feedback on the review comment by checking the appropriate box:

  • 🌟 Awesome comment, a human might have missed that.
  • ✅ Helpful comment
  • 🤷 Neutral
  • ❌ This comment is not helpful

Comment on lines +21 to +22
needs: requires-approval
if: always() && (needs.requires-approval.result == 'success' || needs.requires-approval.result == 'skipped')
Copy link
Contributor

Choose a reason for hiding this comment

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

Logic Error: needs: requires-approval causes test to always skip on non-pull_request_target events

When the workflow is triggered by push or workflow_dispatch, the requires-approval job does not run (its if condition evaluates to false and it is skipped). For a skipped job, needs.requires-approval.result is 'skipped', so the if condition on test correctly resolves to true.

However, with needs: requires-approval, the test job will only be scheduled after requires-approval finishes. On push/workflow_dispatch, requires-approval is skipped immediately, so this should work fine in practice — but it creates an implicit, fragile dependency. If requires-approval is ever changed to result == 'failure' it could block all push-triggered runs silently.

More critically: both test and integration-tests now unconditionally need: requires-approval. For push to main, the job still runs (since skipped is allowed), but the intent is unclear. Consider documenting this with a comment, or restructuring so the dependency is only applied for pull_request_target events.


Please provide feedback on the review comment by checking the appropriate box:

  • 🌟 Awesome comment, a human might have missed that.
  • ✅ Helpful comment
  • 🤷 Neutral
  • ❌ This comment is not helpful

Comment on lines +50 to +52
- uses: actions/checkout@v5
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
Copy link
Contributor

Choose a reason for hiding this comment

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

Security: Checkout of PR head SHA inside a composite action used by pull_request_target exposes secrets to untrusted code

This composite action is called from the integration-tests job which runs under pull_request_target with access to CF secrets (API, username, password, org, space). Checking out github.event.pull_request.head.sha here fetches the PR contributor's code, which is then executed via subsequent steps (e.g., npm install, cds deploy, npm run test). A malicious contributor could embed commands in package.json scripts to exfiltrate the CF credentials.

The same architectural concern applies as in the workflow: the approval gate only fires once and is not re-evaluated on synchronize events. Consider pinning the checkout to the base SHA for secret-consuming workflows, or re-evaluating the approval gate design.


Please provide feedback on the review comment by checking the appropriate box:

  • 🌟 Awesome comment, a human might have missed that.
  • ✅ Helpful comment
  • 🤷 Neutral
  • ❌ This comment is not helpful

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.

2 participants