Skip to content

Fork pull requests execute arbitrary code on the self-hosted macOS and Windows runners #511

Closed

Description

@thcp

macos-check.yml and windows-check.yml run pull-request code on self-hosted runners with no fork guard, on a public repository.

The defect

.github/workflows/macos-check.yml:16-19:

  pull_request:
    paths:
      - "desktop/src-tauri/**"
      - ".github/workflows/macos-check.yml"

runs-on: [self-hosted, macOS, ARM64] (line 32). windows-check.yml:17-20 is the same shape on [self-hosted, windows, x64].

Verified: the repository is PUBLIC, and neither workflow contains any if: condition or head.repo comparison.

The steps run cargo fmt --check, cargo build and cargo clippy. All three execute attacker-supplied code from the PR: build.rs, proc-macro crates, a swapped dependency or [patch] in Cargo.toml. permissions: {} limits the token but does nothing about code execution on the machine.

Why this matters here specifically

The macOS self-hosted runner is the same machine that builds, signs and uploads every DMG and runtime pack. Neither check workflow cleans the workspace, and the release workflows only rm -rf .build dist. An implant in ~/.cargo, ~/.npm, ~/.rustup, or the persistent _work tree survives straight into the next signed release.

GitHub's public-repo default only gates first-time contributors, so one trivial merged PR is enough to unlock this for a subsequent one.

Fix options

  1. Gate both workflows on the PR originating from the repo itself:
    if: github.event.pull_request.head.repo.full_name == github.repository
    Fork PRs then need a maintainer to run the check via workflow_dispatch.
  2. Or move the pull_request trigger to GitHub-hosted runners and keep the self-hosted runner for workflow_dispatch and releases only.

Option 1 preserves the reason the trigger was added (#421: cfg-gated Rust merging without ever being compiled) for the common case, while closing the fork path.

Worth pairing with a workspace clean at the start of the release workflows, so a compromised check run cannot persist into a build.

Activity

  1. added
    ciCI/CD pipeline and automation
    securitySecurity vulnerability or hardening
    on Aug 31, 2026
  2. added a commit that references this issue on Aug 31, 2026
    53ef956
  3. self-assigned this
    on Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

ciCI/CD pipeline and automationsecuritySecurity vulnerability or hardening

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions