Skip to content

fix: pin 6 unpinned action(s),extract 12 unsafe expression(s) to env vars#34350

Closed
dagecko wants to merge 1 commit into
storybookjs:nextfrom
dagecko:runner-guard/fix-ci-security
Closed

fix: pin 6 unpinned action(s),extract 12 unsafe expression(s) to env vars#34350
dagecko wants to merge 1 commit into
storybookjs:nextfrom
dagecko:runner-guard/fix-ci-security

Conversation

@dagecko
Copy link
Copy Markdown

@dagecko dagecko commented Mar 26, 2026

Security: Harden GitHub Actions workflows

Hey, we found some CI/CD security issues in this repo's workflows using Runner Guard, our open-source CI/CD security scanner at Vigilant. These are the same vulnerability classes being actively exploited right now in the tj-actions, Trivy, LiteLLM supply chain attack chain. We scanned the top 50K repos on GitHub and over 20,000 have this same problem. We're trying to get fixes out to as many maintainers as possible before more repos get hit.

This PR fixes what we could automatically, and flags anything else that needs a manual look. There's a real person behind this PR, we're actively checking back on comments so if you have any questions just drop them here and we'll respond.

Fixes applied (in this PR)

Rule Severity File Description
RGS-002 high .github/workflows/code-simplifier.lock.yml Extracted 2 unsafe expression(s) to env vars
RGS-007 high .github/workflows/cron-weekly.yml Pinned 1 third-party action(s) to commit SHA
RGS-002 high .github/workflows/cron-weekly.yml Extracted 1 unsafe expression(s) to env vars
RGS-002 high .github/workflows/duplicate-code-detector.lock.yml Extracted 2 unsafe expression(s) to env vars
RGS-002 high .github/workflows/generate-sandboxes.yml Extracted 2 unsafe expression(s) to env vars
RGS-007 high .github/workflows/handle-release-branches.yml Pinned 1 third-party action(s) to commit SHA
RGS-002 high .github/workflows/handle-release-branches.yml Extracted 3 unsafe expression(s) to env vars
RGS-007 high .github/workflows/nx.yml Pinned 1 third-party action(s) to commit SHA
RGS-002 high .github/workflows/nx.yml Extracted 1 unsafe expression(s) to env vars
RGS-007 high .github/workflows/publish.yml Pinned 1 third-party action(s) to commit SHA
RGS-002 high .github/workflows/publish.yml Extracted 1 unsafe expression(s) to env vars
RGS-007 high .github/workflows/triage.yml Pinned 1 third-party action(s) to commit SHA
RGS-007 high .github/workflows/trigger-circle-ci-workflow.yml Pinned 1 third-party action(s) to commit SHA

Advisory: additional findings (manual review recommended)

| Rule | Severity | File | Description |
| RGS-012 | high | .github/workflows/handle-release-branches.yml | Secret Exfiltration via Outbound HTTP Request |
| RGS-007 | medium | .github/workflows/danger-js.yml | Unpinned Third-Party Action Using Mutable Tag |

Why this matters

GitHub Actions workflows that use untrusted input in run: blocks, expose
secrets inline, or use unpinned third-party actions are vulnerable to
code injection, credential theft, and supply chain attacks. These are the same
vulnerability classes exploited in the tj-actions/changed-files incident
and subsequent supply chain attacks, which compromised CI secrets across
thousands of repositories.

How to verify

Review the diff — each change is mechanical and preserves workflow behavior:

  • Expression extraction (RGS-002/008/014): Moves ${{ }} expressions from
    run: blocks into env: mappings, preventing shell injection
  • SHA pinning (RGS-007): Pins third-party actions to immutable commit SHAs
    (original version tag preserved as comment)
  • Debug env removal (RGS-015): Removes ACTIONS_RUNNER_DEBUG/ACTIONS_STEP_DEBUG
    which leak secrets in workflow logs

Run brew install Vigilant-LLC/tap/runner-guard && runner-guard scan . or install from the
repo to verify.


Found by Runner Guard | Built by Vigilant Cyber Security | Learn more

If this PR is not welcome, just close it -- we won't send another.

Summary by CodeRabbit

  • Chores
    • Improved continuous integration and deployment security by pinning external GitHub Actions to specific commit versions and moving sensitive credentials to workflow environment variables for safer credential handling across automated processes.

…vars

Automated security fixes applied by Runner Guard (https://github.com/Vigilant-LLC/runner-guard).

Changes:
 .github/workflows/code-simplifier.lock.yml         |  6 ++++--
 .github/workflows/cron-weekly.yml                  |  7 +++++--
 .github/workflows/duplicate-code-detector.lock.yml |  6 ++++--
 .github/workflows/generate-sandboxes.yml           |  8 ++++++--
 .github/workflows/handle-release-branches.yml      | 15 +++++++++++----
 .github/workflows/nx.yml                           |  6 ++++--
 .github/workflows/publish.yml                      |  6 ++++--
 .github/workflows/triage.yml                       |  2 +-
 .github/workflows/trigger-circle-ci-workflow.yml   |  2 +-
 9 files changed, 40 insertions(+), 18 deletions(-)
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 26, 2026

📝 Walkthrough

Walkthrough

GitHub Actions workflows across 9 files are updated to inject secrets and context variables into step environment variables rather than directly interpolating them in commands, and to pin GitHub Action references to specific commit SHAs instead of floating version tags.

Changes

Cohort / File(s) Summary
Token/Secret Environment Injection
\.github/workflows/code-simplifier.lock.yml, \.github/workflows/duplicate-code-detector.lock.yml, \.github/workflows/generate-sandboxes.yml, \.github/workflows/handle-release-branches.yml
Updated workflows to inject GITHUB_TOKEN, PAT_STORYBOOK_BOT, and other secrets into step env blocks, then reference them via ${VARIABLE_NAME} in shell commands instead of direct ${{ secrets... }} interpolation.
Git Reference Environment Injection
\.github/workflows/handle-release-branches.yml, \.github/workflows/nx.yml, \.github/workflows/publish.yml
Updated workflows to inject github.ref and related context into step env variables (GIT_REF, REF_NAME), then reference them in conditionals and commands for consistency.
GitHub Action Version Pinning
\.github/workflows/cron-weekly.yml, \.github/workflows/handle-release-branches.yml, \.github/workflows/nx.yml, \.github/workflows/publish.yml, \.github/workflows/triage.yml, \.github/workflows/trigger-circle-ci-workflow.yml
Pinned GitHub Action uses references from floating version tags (e.g., @v1, @v3, @v4) to specific commit SHAs while maintaining equivalent behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/handle-release-branches.yml (1)

100-108: ⚠️ Potential issue | 🟠 Major

Use explicit Authorization header instead of -u for GitHub API token authentication.

Line 104 uses curl -u ${FRONTPAGE_ACCESS_TOKEN}, which expects basic auth format user[:password]. GitHub API recommends using the Authorization header with bearer tokens. The current approach is not the documented best practice and may cause authentication issues.

Suggested patch
       - if: ${{ needs.branch-checks.outputs.is-actionable-branch == 'true' && needs.branch-checks.outputs.is-latest-branch == 'false' && needs.next-release-branch-check.outputs.check == 'false' }}
         run: |
-          curl -X POST https://api.github.com/repos/storybookjs/frontpage/dispatches \
-          -H 'Accept: application/vnd.github.v3+json' \
-          -u ${FRONTPAGE_ACCESS_TOKEN} \
-          --data '{"event_type": "request-create-frontpage-branch", "client_payload": { "branch": "${{ needs.create-next-release-branch.outputs.branch || needs.branch-checks.outputs.branch }}" }}'
+          curl --fail --silent --show-error -X POST https://api.github.com/repos/storybookjs/frontpage/dispatches \
+          -H 'Accept: application/vnd.github+json' \
+          -H "Authorization: Bearer ${FRONTPAGE_ACCESS_TOKEN}" \
+          --data '{"event_type": "request-create-frontpage-branch", "client_payload": { "branch": "${{ needs.create-next-release-branch.outputs.branch || needs.branch-checks.outputs.branch }}" }}'
 
         env:
           FRONTPAGE_ACCESS_TOKEN: ${{ secrets.FRONTPAGE_ACCESS_TOKEN }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/handle-release-branches.yml around lines 100 - 108,
Replace the curl basic-auth usage (-u ${FRONTPAGE_ACCESS_TOKEN}) with an
explicit Authorization header using the bearer token; in the run block that
posts to the GitHub dispatch endpoint (the curl command that sends event_type
"request-create-frontpage-branch" and uses ${FRONTPAGE_ACCESS_TOKEN}), remove
the -u flag and add -H "Authorization: Bearer ${FRONTPAGE_ACCESS_TOKEN}" while
keeping the existing Accept header and the env: FRONTPAGE_ACCESS_TOKEN entry so
the workflow uses the documented token auth method.
🧹 Nitpick comments (1)
.github/workflows/triage.yml (1)

21-21: Good security improvement by pinning the action to a commit SHA.

This change follows security best practices by pinning third-party actions to immutable commit SHAs, preventing potential supply chain attacks where tags could be maliciously updated. The inline comment preserving the version tag (1.10.0) maintains readability.

Note: Consider setting up automated dependency updates (e.g., Dependabot or Renovate) to keep pinned actions up to date, as SHA-pinned actions require more maintenance effort than version tags.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/triage.yml at line 21, You pinned the third‑party action
balazsorban44/nissuer@92ef22afd6a75e5e588f5d689a1fd3433f596f82 while keeping the
inline tag comment 1.10.0 — to reduce maintenance burden add automated
dependency updates: enable Dependabot or Renovate to track and update GitHub
Actions, or add a dependabot.yml that monitors GitHub Actions (so the SHA for
balazsorban44/nissuer is regularly refreshed and PRed), and ensure merge policy
tests the updated action before merging.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/cron-weekly.yml:
- Around line 28-31: Update the curl invocation that posts to Discord: quote the
webhook variable (use "${DISCORD_MONITORING_URL}" instead of
${DISCORD_MONITORING_URL}) and add error-handling flags to ensure failures
propagate (e.g., include --fail-with-body and --show-error and follow redirects
with --location as needed) so that a non-2xx Discord response causes the
workflow to fail; keep the POST to the same JSON payload and ensure the change
is applied to the existing curl line that references DISCORD_MONITORING_URL.

---

Outside diff comments:
In @.github/workflows/handle-release-branches.yml:
- Around line 100-108: Replace the curl basic-auth usage (-u
${FRONTPAGE_ACCESS_TOKEN}) with an explicit Authorization header using the
bearer token; in the run block that posts to the GitHub dispatch endpoint (the
curl command that sends event_type "request-create-frontpage-branch" and uses
${FRONTPAGE_ACCESS_TOKEN}), remove the -u flag and add -H "Authorization: Bearer
${FRONTPAGE_ACCESS_TOKEN}" while keeping the existing Accept header and the env:
FRONTPAGE_ACCESS_TOKEN entry so the workflow uses the documented token auth
method.

---

Nitpick comments:
In @.github/workflows/triage.yml:
- Line 21: You pinned the third‑party action
balazsorban44/nissuer@92ef22afd6a75e5e588f5d689a1fd3433f596f82 while keeping the
inline tag comment 1.10.0 — to reduce maintenance burden add automated
dependency updates: enable Dependabot or Renovate to track and update GitHub
Actions, or add a dependabot.yml that monitors GitHub Actions (so the SHA for
balazsorban44/nissuer is regularly refreshed and PRed), and ensure merge policy
tests the updated action before merging.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0642accf-3bad-440b-a542-4bc28bd74066

📥 Commits

Reviewing files that changed from the base of the PR and between 810093c and df16614.

📒 Files selected for processing (9)
  • .github/workflows/code-simplifier.lock.yml
  • .github/workflows/cron-weekly.yml
  • .github/workflows/duplicate-code-detector.lock.yml
  • .github/workflows/generate-sandboxes.yml
  • .github/workflows/handle-release-branches.yml
  • .github/workflows/nx.yml
  • .github/workflows/publish.yml
  • .github/workflows/triage.yml
  • .github/workflows/trigger-circle-ci-workflow.yml

Comment on lines +28 to +31
curl -H "Content-Type: application/json" -X POST -d '{"content":"The Markdown Links Check workflow has failed in the repository: [storybook]"}' ${DISCORD_MONITORING_URL}

env:
DISCORD_MONITORING_URL: ${{ secrets.DISCORD_MONITORING_URL }} No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify this workflow currently has unquoted webhook usage and no --fail flag.
rg -n -C2 'Send Discord Notification|curl .*DISCORD_MONITORING_URL|--fail|--fail-with-body' .github/workflows/cron-weekly.yml

Repository: storybookjs/storybook

Length of output: 525


Harden the curl invocation for reliable failure signaling.

On line 28, the webhook URL variable is unquoted and curl lacks --fail-with-body; failed notifications will be silently skipped. Quote the variable and add error handling flags to catch Discord API failures.

Suggested patch
-          curl -H "Content-Type: application/json" -X POST -d '{"content":"The Markdown Links Check workflow has failed in the repository: [storybook]"}' ${DISCORD_MONITORING_URL}
+          curl --fail-with-body --silent --show-error \
+            -H "Content-Type: application/json" \
+            -X POST \
+            -d '{"content":"The Markdown Links Check workflow has failed in the repository: [storybook]"}' \
+            "${DISCORD_MONITORING_URL}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
curl -H "Content-Type: application/json" -X POST -d '{"content":"The Markdown Links Check workflow has failed in the repository: [storybook]"}' ${DISCORD_MONITORING_URL}
env:
DISCORD_MONITORING_URL: ${{ secrets.DISCORD_MONITORING_URL }}
curl --fail-with-body --silent --show-error \
-H "Content-Type: application/json" \
-X POST \
-d '{"content":"The Markdown Links Check workflow has failed in the repository: [storybook]"}' \
"${DISCORD_MONITORING_URL}"
env:
DISCORD_MONITORING_URL: ${{ secrets.DISCORD_MONITORING_URL }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/cron-weekly.yml around lines 28 - 31, Update the curl
invocation that posts to Discord: quote the webhook variable (use
"${DISCORD_MONITORING_URL}" instead of ${DISCORD_MONITORING_URL}) and add
error-handling flags to ensure failures propagate (e.g., include
--fail-with-body and --show-error and follow redirects with --location as
needed) so that a non-2xx Discord response causes the workflow to fail; keep the
POST to the same JSON payload and ensure the change is applied to the existing
curl line that references DISCORD_MONITORING_URL.

@dagecko dagecko closed this by deleting the head repository Mar 26, 2026
@dagecko
Copy link
Copy Markdown
Author

dagecko commented Mar 28, 2026

Resubmitted as #34380. Had a problem with my fork, apologies for the noise.

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