Fix expression injection in cross-repo GitHub Actions workflow (#18316)
## Summary
- Fixes a script injection vulnerability in the `claude-cross-repo`
job's `actions/github-script` step where `${{ steps.prompt.outputs.repo
}}` and `${{ steps.prompt.outputs.issue_number }}` were interpolated
directly into JavaScript string literals. A crafted dispatch payload
could inject arbitrary JavaScript with access to
`secrets.TWENTY_DISPATCH_TOKEN`.
- Values are now passed via `env:` and accessed through `process.env`,
which treats them as data rather than code.
## Context
Motivated by the [hackerbot-claw
campaign](https://www.stepsecurity.io/blog/hackerbot-claw-github-actions-exploitation)
which exploited similar `${{ }}` expression injection patterns in
workflows at Microsoft, DataDog, and CNCF projects.
The broader analysis found that our workflow is **not vulnerable** to
the primary attack vector (Pwn Request via `pull_request_target` +
untrusted checkout), and `claude-code-action` already gates on write
access internally. This expression injection in the cross-repo dispatch
job was the only concrete vulnerability identified.
## Test plan
- [ ] Verify the `claude-cross-repo` job still posts comments back to
the source issue after a dispatch run
- [ ] Confirm `TARGET_REPO` and `TARGET_ISSUE` env vars are correctly
resolved from step outputs
Made with [Cursor](https://cursor.com)
This commit is contained in:
@@ -160,11 +160,14 @@ jobs:
|
||||
- name: Post response to source issue
|
||||
if: always()
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
TARGET_REPO: ${{ steps.prompt.outputs.repo }}
|
||||
TARGET_ISSUE: ${{ steps.prompt.outputs.issue_number }}
|
||||
with:
|
||||
github-token: ${{ secrets.TWENTY_DISPATCH_TOKEN }}
|
||||
script: |
|
||||
const [owner, repo] = '${{ steps.prompt.outputs.repo }}'.split('/');
|
||||
const issueNumber = parseInt('${{ steps.prompt.outputs.issue_number }}', 10);
|
||||
const [owner, repo] = process.env.TARGET_REPO.split('/');
|
||||
const issueNumber = parseInt(process.env.TARGET_ISSUE, 10);
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
|
||||
Reference in New Issue
Block a user