Conversation
There was a problem hiding this comment.
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
| - uses: actions/checkout@v5 | ||
| with: | ||
| ref: ${{ github.event.pull_request.head.sha || github.sha }} |
There was a problem hiding this comment.
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:
- Keeping secrets-consuming jobs isolated from PR head code (fetch only metadata, not run contributed code), or
- Using a two-workflow split: a trusted
push/pull_request_targetworkflow that only saves artifacts, and a separateworkflow_runtriggered 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
| needs: requires-approval | ||
| if: always() && (needs.requires-approval.result == 'success' || needs.requires-approval.result == 'skipped') |
There was a problem hiding this comment.
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
| - uses: actions/checkout@v5 | ||
| with: | ||
| ref: ${{ github.event.pull_request.head.sha || github.sha }} |
There was a problem hiding this comment.
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
Fix CI Workflow to Properly Handle
pull_request_targetEventsChore
🔧 Updated CI workflow and integration test action to correctly handle
pull_request_targetevents, ensuring PRs from external forks are checked out at the correct commit SHA and approval gating is applied consistently.Changes
.github/workflows/test.yml:requires-approvalcondition to checkhead.repo.owner.logininstead ofbase.user.loginfor proper fork detection.needs: requires-approvaland the correspondingifcondition to bothtestandintegration-testsjobs, ensuring they wait for approval when triggered from forks.actions/checkoutfromv2/v4tov5andactions/setup-nodefromv2tov4.ref: ${{ github.event.pull_request.head.sha || github.sha }}to checkout steps to ensure the PR head commit is used (important forpull_request_targetsecurity)..github/actions/integration-tests/action.yml:actions/checkoutfromv2tov5with the same explicitreffor the correct commit SHA.actions/setup-nodefromv2tov4and aligned node version input references to useinputs.NODE_VERSION.📬 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 | 💬 Feedbackpull_request.opened79bfa020-22e6-11f1-9efe-0023cd0d2de3anthropic--claude-4.6-sonnet