Skip to content

fix: pin 35 unpinned action(s),extract 22 unsafe expression(s) to env vars#8605

Closed
dagecko wants to merge 1 commit intoAppFlowy-IO:mainfrom
dagecko:runner-guard/fix-ci-security
Closed

fix: pin 35 unpinned action(s),extract 22 unsafe expression(s) to env vars#8605
dagecko wants to merge 1 commit intoAppFlowy-IO:mainfrom
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/build_command.yml Extracted 1 unsafe expression(s) to env vars
RGS-007 high .github/workflows/commit_lint.yml Pinned 1 third-party action(s) to commit SHA
RGS-007 high .github/workflows/docker_ci.yml Pinned 2 third-party action(s) to commit SHA
RGS-007 high .github/workflows/flutter_ci.yaml Pinned 6 third-party action(s) to commit SHA
RGS-007 high .github/workflows/ios_ci.yaml Pinned 4 third-party action(s) to commit SHA
RGS-007 high .github/workflows/mobile_ci.yml Pinned 1 third-party action(s) to commit SHA
RGS-007 high .github/workflows/ninja_i18n.yml Pinned 1 third-party action(s) to commit SHA
RGS-007 high .github/workflows/release.yml Pinned 13 third-party action(s) to commit SHA
RGS-002 high .github/workflows/release.yml Extracted 21 unsafe expression(s) to env vars
RGS-007 high .github/workflows/rust_ci.yaml Pinned 3 third-party action(s) to commit SHA
RGS-007 high .github/workflows/rust_coverage.yml Pinned 3 third-party action(s) to commit SHA
RGS-007 high .github/workflows/translation_notify.yml Pinned 1 third-party action(s) to commit SHA

Advisory: additional findings (manual review recommended)

| Rule | Severity | File | Description |
| RGS-002 | critical | .github/workflows/release.yml | Expression Injection via Branch Name or Untrusted Input |
| RGS-014 | high | .github/workflows/mobile_ci.yml | Expression Injection via workflow_dispatch Input |
| RGS-012 | high | .github/workflows/mobile_ci.yml | Secret Exfiltration via Outbound HTTP Request |
| RGS-012 | high | .github/workflows/mobile_ci.yml | Secret Exfiltration via Outbound HTTP Request |
| RGS-012 | high | .github/workflows/release.yml | Secret Exfiltration via Outbound HTTP Request |
| RGS-012 | high | .github/workflows/release.yml | Secret Exfiltration via Outbound HTTP Request |

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)

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 Sourcery

Harden GitHub Actions workflows by pinning third-party actions to specific commit SHAs and isolating GitHub context and secrets usage via environment variables to reduce injection and supply-chain risk.

CI:

  • Pin multiple GitHub Actions across release, Flutter, iOS, Rust, Docker, commit lint, Slack, and translation workflows to immutable commit SHAs instead of floating tags.
  • Refactor release, build, and notification workflows to pass GitHub context values and secrets through env variables before use in shell commands and HTTP requests, mitigating expression and secret injection risks.

… vars

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

Changes:
 .github/workflows/build_command.yml      |  5 +-
 .github/workflows/commit_lint.yml        |  2 +-
 .github/workflows/docker_ci.yml          |  4 +-
 .github/workflows/flutter_ci.yaml        | 12 ++--
 .github/workflows/ios_ci.yaml            |  8 +--
 .github/workflows/mobile_ci.yml          |  2 +-
 .github/workflows/ninja_i18n.yml         |  2 +-
 .github/workflows/release.yml            | 98 +++++++++++++++++++++-----------
 .github/workflows/rust_ci.yaml           |  6 +-
 .github/workflows/rust_coverage.yml      |  6 +-
 .github/workflows/translation_notify.yml |  2 +-
 11 files changed, 92 insertions(+), 55 deletions(-)
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Mar 26, 2026

Reviewer's Guide

Hardens multiple GitHub Actions workflows by pinning third-party actions to specific commit SHAs and moving inline GitHub/secret expressions out of shell commands into env variables to reduce injection and supply-chain risk, while preserving existing CI/CD behavior.

Sequence diagram for the hardened release workflow using env vars and pinned actions

sequenceDiagram
  actor Developer
  participant GitHub
  participant ReleaseWorkflow
  participant FlutterAction as subosito_flutter_action_pinned
  participant RustToolchain as actions_rs_toolchain_pinned
  participant DockerBuildx as docker_setup_buildx_pinned
  participant DockerBuildPush as docker_build_push_pinned
  participant MacSigner as macos_codesign_tools
  participant AppleNotary as apple_notary_service
  participant Discord as discord_api

  Developer->>GitHub: Push tag ref (release version)
  GitHub->>ReleaseWorkflow: Trigger release_yml on tag

  Note over ReleaseWorkflow: Initialize env REF_NAME from github_ref_name

  ReleaseWorkflow->>ReleaseWorkflow: Build release notes using ${REF_NAME}

  ReleaseWorkflow->>FlutterAction: Setup Flutter (pinned SHA)
  FlutterAction-->>ReleaseWorkflow: Flutter available

  ReleaseWorkflow->>RustToolchain: Install Rust toolchain (pinned SHA)
  RustToolchain-->>ReleaseWorkflow: Rust toolchain ready

  Note over ReleaseWorkflow: Use env REF_NAME in flutter and cargo build commands

  ReleaseWorkflow->>MacSigner: Decode MACOS_CERTIFICATE env and import key
  MacSigner-->>ReleaseWorkflow: Signing identities configured

  ReleaseWorkflow->>MacSigner: Codesign AppFlowy using MACOS_CODESIGN_ID env
  MacSigner-->>ReleaseWorkflow: Signed macOS app

  ReleaseWorkflow->>AppleNotary: Notarize dmg with MACOS_NOTARY_USER, MACOS_TEAM_ID, MACOS_NOTARY_PWD env
  AppleNotary-->>ReleaseWorkflow: Notarization success

  ReleaseWorkflow->>DockerBuildx: Setup Buildx (pinned SHA)
  DockerBuildx-->>ReleaseWorkflow: Builder ready

  ReleaseWorkflow->>DockerBuildPush: Build and push Docker image (pinned SHA)
  DockerBuildPush-->>ReleaseWorkflow: Image pushed

  Note over ReleaseWorkflow: Prepare DISCORD env from secret

  ReleaseWorkflow->>Discord: POST webhook using ${DISCORD} env
  Discord-->>ReleaseWorkflow: Notification accepted
Loading

File-Level Changes

Change Details Files
Pin third-party GitHub Actions to immutable commit SHAs across workflows to mitigate supply-chain attacks.
  • Replace version tags (e.g., @v2, @V3, @stable, @master) for commonly used actions with specific commit SHAs, preserving the original tag as a comment for traceability.
  • Update build, test, coverage, Docker, notification, and tooling steps to use pinned SHAs without changing their inputs or logic.
.github/workflows/release.yml
.github/workflows/flutter_ci.yaml
.github/workflows/ios_ci.yaml
.github/workflows/rust_ci.yaml
.github/workflows/rust_coverage.yml
.github/workflows/docker_ci.yml
.github/workflows/commit_lint.yml
.github/workflows/mobile_ci.yml
.github/workflows/ninja_i18n.yml
.github/workflows/translation_notify.yml
Extract GitHub context, secrets, and other expressions from shell commands into environment variables to limit expression and shell injection surface.
  • Introduce named env variables (e.g., REF_NAME, TOKEN, DISCORD, MACOS_* values) bound to ${{ github.* }} or ${{ secrets.* }} expressions and reference them via ${VAR} in run steps.
  • Update sed, Dart, cargo, shell scripts, curl, codesigning, notarization, and GitHub API calls to consume these env variables instead of embedding expressions directly in the shell.
  • Ensure the semantics of paths, versions, and credentials remain unchanged by only refactoring how values are passed into commands.
.github/workflows/release.yml
.github/workflows/build_command.yml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 26, 2026

CLA assistant check
All committers have signed the CLA.

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • There are several places where you duplicate REF_NAME: ${{ github.ref_name }} env blocks on multiple steps in release.yml; consider defining REF_NAME at the job level to reduce repetition and keep the value consistent across all steps.
  • In the final Discord notification step in release.yml, you still interpolate ${{ github.ref_name }} directly inside the JSON string; for consistency and easier editing, you might move this into an env var (e.g. REF_NAME) and reference it in the curl payload instead.
  • For opral/ninja-i18n-action you pinned to a raw commit with a # main comment; if the action exposes version tags, consider pinning to a commit hash that corresponds to a released tag and reflecting that in the comment (e.g. # vX.Y.Z) to make future upgrades clearer.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- There are several places where you duplicate `REF_NAME: ${{ github.ref_name }}` env blocks on multiple steps in `release.yml`; consider defining `REF_NAME` at the job level to reduce repetition and keep the value consistent across all steps.
- In the final Discord notification step in `release.yml`, you still interpolate `${{ github.ref_name }}` directly inside the JSON string; for consistency and easier editing, you might move this into an env var (e.g. `REF_NAME`) and reference it in the `curl` payload instead.
- For `opral/ninja-i18n-action` you pinned to a raw commit with a `# main` comment; if the action exposes version tags, consider pinning to a commit hash that corresponds to a released tag and reflecting that in the comment (e.g. `# vX.Y.Z`) to make future upgrades clearer.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

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