chore(security): pin Actions to SHAs + enable Dependabot auto-bumps - #2213
Merged
Merged
Conversation
Supply-chain hardening for the CI pipeline. 23 workflow files
modified, 59 mutable-tag refs replaced with commit SHAs.
The risk
Every `uses:` reference in .github/workflows/*.yml was pinned to a
mutable tag (e.g., `actions/checkout@v4`). A maintainer of an
action — or a compromised maintainer account — can repoint that
tag to malicious code, and our pipelines silently pull it on the
next run. The tj-actions/changed-files compromise of March 2025 is
the canonical example: maintainer credential leak, attacker
repointed several `@v<N>` tags to a payload that exfiltrated
repository secrets. Repos that pinned to SHAs were unaffected.
The fix
Replace each `@v<N>` with `@<commit-sha> # v<N>`. The trailing
comment preserves human readability ("ah, this is v4"); the SHA
makes the reference immutable.
Actions covered (10 distinct):
actions/{checkout,setup-go,setup-python,setup-node,upload-artifact,github-script}
docker/{login-action,setup-buildx-action,build-push-action}
github/codeql-action/{init,autobuild,analyze}
dorny/paths-filter
imjasonh/setup-crane
pnpm/action-setup (already pinned in molecule-app, listed here for completeness)
Excluded:
Molecule-AI/molecule-ci/.github/workflows/disable-auto-merge-on-push.yml@main
— internal org reusable workflow; we control its repo, threat model
is different from third-party actions. Conventional to pin to @main
rather than SHA for internal reusables.
The maintenance cost
SHA pinning means upstream fixes require manual SHA bumps. Without
automation, pinned SHAs go stale. So this PR also enables Dependabot
across four ecosystems:
- github-actions (workflows)
- gomod (workspace-server)
- npm (canvas)
- pip (workspace runtime requirements)
Weekly cadence — the supply-chain attack window is "minutes between
repoint and pull"; weekly auto-bumps don't help with zero-days
regardless. The point is to pull in non-zero-day fixes without
operator effort.
Aligns with user-stated principle: "long-term, robust, fully-
automated, eliminate human error."
Companion PR: Molecule-AI/molecule-controlplane#308 (same pattern,
smaller surface).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HongmingWang-Rabbit
requested a review
from hongmingwang-moleculeai
as a code owner
April 28, 2026 22:37
HongmingWang-Rabbit
pushed a commit
that referenced
this pull request
Jun 12, 2026
… + settle /buildinfo (#2213) Root cause of the #2213 main-red (`publish-workspace-server-image / Production auto-deploy` failing on hongming "is stale"): Two main pushes landed ~2 min apart (7a72516 then 7f25373). With no `concurrency:` on this workflow (intentional — Gitea 1.22.6 cancels queued prod deploys) BOTH deploy-production jobs run. The OLDER 7a72516 job started late, after 7f25373 was already main's head. The #2194 superseded guard only protected the *verify* step — it ran AFTER the redeploy and the :latest promote. So the older job still: 1. redeployed the canary (hongming) BACKWARD to staging-7a72516, reverting it from the newer SHA the 7f25373 job had just shipped — which is exactly what the 7f25373 job's verify then saw ("hongming is stale: actual=7a72516, expected=7f25373") -> main red; AND 2. promoted :latest BACKWARD to the older staging-7a72516 image, before finally skipping verify and exiting green. Fix (defense in depth, no change to the redeploy/rollout logic itself): - Add a "Check superseded before production side effects" step that runs the existing check-superseded BEFORE the rollout. When a newer commit already owns main, gate OFF both the redeploy-fleet step and the :latest promote so an older job never rolls the fleet (or :latest) backward. Fail-safe: an unreadable head is treated as NOT superseded, so a genuine deploy never silently skips. The in-step verify guard is kept to catch a newer job that lands DURING this job's rollout. - Harden the /buildinfo verify with a bounded per-tenant settle budget (default 240s, 20s interval, both overridable via repo vars). `curl --retry` only retries connection/5xx failures, not a stale-but-200 body, so a tenant whose container the CP just swapped — still serving the draining old image at the edge — false-reds "stale" on the first poll. Now we poll until the tenant reports the target SHA or the budget is exhausted, then fail loud. A genuinely stuck tenant is NOT masked. Tests: pin the superseded contract for the exact 7a72516/7f25373 incident shape (older job superseded -> skip; latest job -> still rolls + verifies). All 35 prod-auto-deploy unit tests pass; lint-workflow-yaml + curl-status linters clean; every run block bash -n clean. Refs #2213 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supply-chain hardening across 23 workflow files. Pin every `uses:` ref to a commit SHA + enable Dependabot for auto-bumps. Companion to Molecule-AI/molecule-controlplane#308.
The risk
Mutable tags (`actions/checkout@v4`) are a known supply-chain attack vector. The tj-actions/changed-files compromise of March 2025 is the canonical example: maintainer credential leak → attacker repointed `@v` tags to a payload that exfiltrated repository secrets. SHA pinning closes that risk.
What this PR does
Actions covered (10 distinct, 59 references)
`actions/checkout`, `actions/setup-go`, `actions/setup-python`, `actions/setup-node`, `actions/upload-artifact`, `actions/github-script`, `docker/login-action`, `docker/setup-buildx-action`, `docker/build-push-action`, `github/codeql-action/{init,autobuild,analyze}`, `dorny/paths-filter`, `imjasonh/setup-crane`, `pnpm/action-setup`.
Intentionally excluded
`Molecule-AI/molecule-ci/.github/workflows/disable-auto-merge-on-push.yml@main` — internal org reusable workflow. We control its repo; threat model is different from third-party actions. Conventional to pin to `@main` rather than SHA for internal reusables.
Test plan
🤖 Generated with Claude Code