Skip to content

sync-upstream.yml dispatches CI on a branch that carries upstream's .github/ tree: an upstream workflow change would run with this repository's token and secrets #163

Closed

Description

@Nawid3333

Severity: high

Where: .github/workflows/sync-upstream.yml (merge + authgit push -f origin "$SYNC_BRANCH", then gh workflow run ci.yml --ref "$SYNC_BRANCH" and gh workflow run dependency-review.yml --ref "$SYNC_BRANCH"); .github/workflows/update-prs.yml (the ".github/ changed: a person reads that" check, which runs only after CI did)

What happens

workflow_dispatch --ref <branch> runs the workflow file as it exists on that branch. The sync branch is a merge of Andrews54757/FastStream's main into this repository's main, pushed into this repository (not a fork), so every repository secret is reachable from a run on it. If upstream's tree ever carries a change to .github/workflows/ci.yml or dependency-review.yml (an upstream compromise, a takeover of the upstream account, or simply Andrew adding a workflow with the same path), that file is executed with this repository's GITHUB_TOKEN (whatever permissions the modified file declares, up to the repository's maximum) and can read secrets.AMO_API_KEY, secrets.AMO_API_SECRET (used by release.yml) and secrets.UPDATE_PRS_TOKEN (the owner's fine-grained token with Workflows: write) through ${{ secrets.* }}. update-prs.yml's "it changes .github/, a person reads that" is evaluated after that CI run already executed.

patched-libraries.yml, toolchain-updates.yml and vendored-updates.yml dispatch onto branches they build from main themselves, so they are not exposed the same way.

Suggested fix

  1. In sync-upstream.yml, before any dispatch: git diff --quiet "$BASE_SHA" HEAD -- .github/ || { echo "upstream changed .github/: not dispatching CI; a person reviews first"; ...; } and skip both gh workflow run calls (the PR comment says why).
  2. Move AMO_API_KEY, AMO_API_SECRET and UPDATE_PRS_TOKEN into a GitHub Environment whose deployment-branch policy allows only main and v* tags, and reference environment: from release.yml, amo-signing-failsafe.yml and update-prs.yml, so no branch workflow can read them.
  3. Confirm the repository's default GITHUB_TOKEN permission is "read" so a modified workflow cannot escalate by declaring permissions: write-all.

Confidence: high.


From a line-by-line code review of the tree at 41363fd (2026-10-02). Each claim above was checked against the source before filing; the reproduction steps and line references are as of that commit.


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    code-reviewFound by the 2026-10-02 line-by-line reviewsecuritySecurity finding

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions