Skip to content

Workflow security fixes for the release pipelines - #4839

Open
Totara-thib wants to merge 4 commits into
Kareadita:developfrom
Totara-thib:ci-hardening
Open

Workflow security fixes for the release pipelines#4839
Totara-thib wants to merge 4 commits into
Kareadita:developfrom
Totara-thib:ci-hardening

Conversation

@Totara-thib

Copy link
Copy Markdown

Changed

  • Changed: All workflow actions are now referenced by an exact commit instead of a floating tag, so the release and publish pipelines only ever run action code that existed at review time. Versions stay exactly where they were.
  • Changed: Workflow jobs now declare the minimal token permissions they need. Only the issue commenter keeps a write scope, the docker publish jobs already had theirs scoped.

Fixed

  • Fixed: Fixed a shell injection risk in the debug steps of the nightly and stable workflows. Values now pass through environment variables, the printed output is unchanged.
  • Fixed: Fixed the canary version bump referencing a GitHub repository that no longer exists, which would fail the next canary build. It now uses the same maintained fork the nightly workflow already uses, pinned like the rest.

The debug jobs in the nightly and stable workflows expanded template
expressions directly inside the shell script, including one built on
github.head_ref, which is attacker-controlled on pull request events.
The stable workflow triggers on closed pull requests, so a crafted
branch name could inject shell commands into that runner. Passing the
values through environment variables keeps the output identical and
removes the injection path.
The canary workflow still referenced SiqiLu/dotnet-bump-version, a
repository that no longer exists on GitHub, so the next canary push
would fail at action download. Worse, a deleted repository name can be
re-registered by anyone, and whoever claims it would run their code in
this workflow with its token. The nightly workflow already switched to
the majora2007 fork, this aligns the canary workflow with it, pinned
by commit SHA.
The nightly, canary and stable workflows push images to Docker Hub
and ghcr.io and bump versions with a repository PAT, and all of their
actions were referenced by floating tags. A tag is a movable pointer,
whoever controls an action repository can point it at different code
after the fact, which is how the tj-actions/changed-files incident
(CVE-2025-30066) leaked CI secrets from thousands of repositories. An
exact commit cannot be retargeted.

Every pin keeps the version as a trailing comment so it can be
checked against the action's releases page. Versions stay exactly
where they were, nothing is upgraded.
The docker publish jobs already scoped their own tokens, this extends
the same discipline to the rest. Only the issue commenter keeps a
write scope, it posts comments on the issues linked to a release. The
debug and merge marker jobs get an empty grant since they never touch
the API, and the version bump and documentation jobs authenticate
with the repository PAT so their workflow token drops to read only.
@Totara-thib

Copy link
Copy Markdown
Author

Extra context since I have not raised this through an issue or Discord first, per the template note.

Why these changes, in security terms:

The stable workflow triggers on closed pull requests against develop, and its debug step expanded an expression built on github.head_ref inside a shell script. A branch name is attacker-controlled on pull request events, so a crafted name could inject shell commands into the runner that holds the publish credentials. Environment variable indirection removes that path with identical output.

SiqiLu/dotnet-bump-version is gone from GitHub. Beyond breaking the canary build at action download, a deleted repository name can be re-registered by anyone, and whoever claims it would run their code in that workflow. Pointing at the majora2007 fork restores what the workflow did before the upstream repo vanished.

On the pins: a version tag is a movable pointer, whoever controls an action repository can point it at different code after the fact. The tj-actions/changed-files incident (CVE-2025-30066) leaked CI secrets from thousands of repositories exactly this way. An exact commit cannot be retargeted. Each pin keeps the version as a trailing comment so it can be checked against the releases page, and if you ever enable Dependabot for github-actions it understands the format and keeps pins updated.

One heads-up: if the org ever restricts allowed actions in the repo settings with tag patterns such as owner/action@v3, those patterns stop matching SHA refs and workflows fail at startup. The fix is owner/action@* in that setting. Nothing to do if no such restriction is configured.

Found and fixed by Plumber's analysis, reviewed and submitted by me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

2 participants