Issue

tl;dr

Our way to fix linting on pull requests (by commenting @nf-core-bot fix linting) ran code from the pull request with the shared bot token available, which could allowe attackers to steal the token.

The nf-core pipeline template ships a GitHub Actions workflow that fixes code formatting when someone comments @nf-core-bot fix linting on a pull request. For it to push the fixes back, even to pull requests from forks, the workflow checked out the repository with the organization-wide nf-core bot token, which then stayed stored in the job’s git configuration. It then checked out the pull request and ran the formatting tools on it.

Those tools read their configuration from the pull request itself. A .pre-commit-config.yaml can define a hook that runs any command, and a prettier configuration can load a plugin, so whoever wrote the pull request also decided what code the job ran. The workflow also did not check who posted the comment, so the author of a pull request from a fork could trigger it themselves.

In short: anyone on GitHub, with no prior access to nf-core, could open a pull request with a modified lint configuration against an affected pipeline, comment @nf-core-bot fix linting, and run their own code on nf-core’s CI with the bot token on disk. With that token they could impersonate the nf-core bot anywhere it reaches: pushing commits, posting comments, and more.

This affects pipelines whose default branch contains the old workflow. Pipelines created or last synchronized with nf-core/tools 3.3.0 through 4.1.0 have it as .github/workflows/fix_linting.yml, older pipelines as .github/workflows/fix-linting.yml. To check whether a fix-linting.yml is the old or the fixed version, look at its fix-linting job. The fixed file only contains uses: nf-core/actions/.github/workflows/fix-linting.yml@v1 and no steps: of its own. The old file lists its own steps, among them run: gh pr checkout ${{ github.event.issue.number }}. The fix touches the following workflow files:

.github/workflows
├── fix_linting.yml (removed)
└── fix-linting.yml (added, or replaced if it has the old content)

Resolution

tl;dr

An automated patch PR against the default branch will fix the vulnerability for nf-core pipelines. It will be merged by the nf-core infrastructure team.

nf-core/tools 4.2.0 fixes this by replacing the workflow with a short stub that calls a reusable fix-linting workflow from nf-core/actions. That workflow runs the lint tools on the pull request’s code in a job without access to any secrets. A separate job checks the result and pushes it with the bot token, without ever running the pull request’s code. It also checks who posted the comment: only the pull request’s author or someone with write access can trigger a fix, and only admins can trigger one on a protected branch. This closes the path to running arbitrary code and stealing the bot token.

Workflows triggered by a comment always run using the workflow definition from the repository’s default branch, not from the pull request. Until the fix is merged into the default branch, GitHub keeps running the old, vulnerable workflow. Pipeline maintainers should therefore merge the automated patch pull request opened against their default branch as soon as possible (the nf-core infrastructure team will also go through PRs and merge them). The dev branch gets the same change with the next template sync. No new pipeline release is required after the fix is merged, because it only affects CI workflows and not the actual pipeline code.

Pipelines outside nf-core are not affected by this vulnerability, except for those that have set their own NF_CORE_BOT_AUTH_TOKEN secret on GitHub. In that case, you should replace fix_linting.yml (or an old fix-linting.yml) with the new template file and rotate the NF_CORE_BOT_AUTH_TOKEN secret.

References