Skip to content

ci: pin the Docker Hub and CLA actions and scope every workflow token - #5680

Open
Totara-thib wants to merge 3 commits into
apolloconfig:masterfrom
Totara-thib:ci-workflow-hardening
Open

Totara-thib wants to merge 3 commits into
apolloconfig:masterfrom
Totara-thib:ci-workflow-hardening

Conversation

@Totara-thib

@Totara-thib Totara-thib commented Sep 24, 2026 •

Copy link
Copy Markdown

What's the purpose of this PR

Pins the third-party actions to commit SHAs, scopes the workflow token per job, and stops checkouts from keeping the token. One commit each, no change in what the workflows do.

A tag like docker/login-action@v2 can be repointed by whoever controls the action repo, and the next run picks up the new code. That is how tj-actions/changed-files leaked CI secrets in March 2025 (CVE-2025-30066). The sharpest case here is cla.yml: it runs on pull_request_target and hands the repo-scoped CLA token to cla-assistant/github-action@v2.1.2-beta, a floating beta tag of an action that is now archived upstream. The Docker Hub token that pushes the apollo images sits behind tags too.

  • Each SHA is the commit the current tag points to today, tag kept as a comment and easy to check with git ls-remote.
  • Nine workflows had no permissions: block. Most jobs now only read, and the CLA and license jobs keep pull-requests: write since they comment on PRs.
  • persist-credentials: false on all checkouts, nothing pushes through git.

First-party actions keep their tags, pinning those too would help an OpenSSF Scorecard score. There is no Dependabot config here, if you add one for github-actions it bumps the SHA and the comment together.

If your org restricts allowed actions with tag patterns like owner/action@v1, those stop matching SHAs. owner/action@* fixes it.

Unrelated, but commit_lint.yml triggers on PRs to main while the default branch is master, so it never runs.

Which issue(s) this PR fixes:

None, this is a CI hardening change.

Brief changelog

  • Pin third-party actions to commit SHAs
  • Scope the workflow token per job
  • Stop persisting the checkout token

Follow this checklist to help us incorporate your contribution quickly and easily:

  • Read the Contributing Guide before making this pull request.
  • Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
  • Write necessary unit tests to verify the code.
  • Run mvn clean test to make sure this pull request doesn't break anything.
  • Run mvn spotless:apply to format your code.
  • Update the CHANGES log. (I'll add the entry once this PR has a number)

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

Summary by CodeRabbit

  • Security
    • Tightened automation permissions to grant only the access needed for each workflow.
    • Prevented checkout steps from retaining Git credentials and pinned several third-party actions to specific versions.

Tags on third-party actions can be moved by whoever controls the action
repository, and the next run then executes that code with this repo's
credentials: the Docker Hub token in docker-publish, and the repo-scoped
CLA personal access token that cla.yml hands to a floating beta tag
under pull_request_target.

Each action now points at the commit its current tag resolves to today,
so nothing changes in behavior. The tag stays in a trailing comment and
can be checked with git ls-remote. Dependabot understands this format
and bumps the SHA and the comment together if version updates are ever
enabled for github-actions. First-party actions (actions/*, github/*)
stay on their tags.
Nine workflows had no permissions block, so their GITHUB_TOKEN got
whatever the repository default grants, including the Docker Hub
publish job and the pull_request_target CLA job.

The scopes below come from what each job actually calls:
- build, docker publish and validation, discovery smoke and the portal
  e2e runs only read the tree, they get contents: read.
- commit lint lists the PR commits, it gets pull-requests: read.
- the CLA job comments on and locks the PR and reads its own run history
  with the workflow token (signatures and re-runs go through the CLA
  PAT), so it keeps actions: read and pull-requests: write.
- license-eye posts review comments when a header check fails, so the
  license job keeps pull-requests: write.
actions/checkout writes the workflow token into .git/config by default
and leaves it there for every later step, including the Maven builds,
the Docker image builds and the release packaging that runs with
contents: write. None of these workflows pushes through git: the
release upload authenticates gh with GH_TOKEN and the OpenAPI check
only fetches the public base branch, so all 14 checkouts can set
persist-credentials: false.
@github-actions

github-actions Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: a5e291bd-1e50-4c5c-95bd-404296de2a65

📥 Commits

Reviewing files that changed from the base of the PR and between bb0725d and 0bdae82.

📒 Files selected for processing (14)
  • .github/workflows/build.yml
  • .github/workflows/cla.yml
  • .github/workflows/code-style-check.yml
  • .github/workflows/codeql.yml
  • .github/workflows/commit_lint.yml
  • .github/workflows/docker-publish.yml
  • .github/workflows/docker-validation.yml
  • .github/workflows/external-discovery-smoke.yml
  • .github/workflows/javascript-test.yml
  • .github/workflows/license.yml
  • .github/workflows/openapi-compatibility.yml
  • .github/workflows/portal-login-e2e.yml
  • .github/workflows/portal-ui-e2e.yml
  • .github/workflows/release-packages.yml

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The workflows restrict token permissions where specified, disable checkout credential persistence, and pin selected third-party actions to commit SHAs.

Changes

Workflow hardening

Layer / File(s) Summary
Token permissions and checkout credentials
.github/workflows/build.yml, .github/workflows/cla.yml, .github/workflows/code-style-check.yml, .github/workflows/codeql.yml, .github/workflows/commit_lint.yml, .github/workflows/docker-publish.yml, .github/workflows/docker-validation.yml, .github/workflows/external-discovery-smoke.yml, .github/workflows/javascript-test.yml, .github/workflows/license.yml, .github/workflows/openapi-compatibility.yml, .github/workflows/portal-login-e2e.yml, .github/workflows/portal-ui-e2e.yml, .github/workflows/release-packages.yml
Workflows add contents: read permissions where specified. The CLA and license jobs also define job-scoped permissions, including pull-requests: write. Checkout steps disable persisted credentials.
Pinned action references
.github/workflows/build.yml, .github/workflows/cla.yml, .github/workflows/docker-publish.yml
Selected retry, Codecov, CLA Assistant, and Docker action references use commit SHAs instead of version tags. The commitlint reference is also pinned to a commit SHA in its workflow.

Estimated code review effort: 2 (Simple) | ~12 minutes

Suggested reviewers: nobodyiam

Merge Risk: ⚪ Minimal · up to 0bdae

The workflow changes narrow token access, disable checkout credential persistence, and pin selected actions. No concrete behavior or security regression is evident, so the PR appears ready for normal checks.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main changes: pinning CI actions and restricting workflow token permissions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Totara-thib

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@Totara-thib

Copy link
Copy Markdown
Author

recheck

This branch has not been deployed

No deployments
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.

1 participant