Skip to content

chore(ci): split publish from build, drop Actions cache from privileged workflows#62

Merged
mandarini merged 1 commit into
mainfrom
ci/split-publish-job
May 12, 2026
Merged

chore(ci): split publish from build, drop Actions cache from privileged workflows#62
mandarini merged 1 commit into
mainfrom
ci/split-publish-job

Conversation

@mandarini
Copy link
Copy Markdown
Collaborator

Closes the OIDC-theft and cache-poisoning vectors that the TanStack/router compromise (2026-05-11) and Adnan Khan's cache-poisoning research describe.

What changed

release.yml split into two jobs:

  • buildcontents: write + pull-requests: write (release-please). Runs install/build/pack and uploads the .tgz as an artifact. No id-token.
  • publish-npmneeds: build, only job with id-token: write. Downloads the tarball into ./publish/ (scratch dir per GHSL Part 4), runs npm publish --provenance on the .tgz. Never runs pnpm install or any third-party code.

JSR publish and GH pre-release stay in the build job (JSR uses its own OIDC binding scoped to JSR, not npm).

Dropped cache: pnpm from docs.yml and ci.yml:
A compromised dep on a main-branch workflow can steal the GitHub Actions cache token and poison entries that other privileged workflows on main will restore. release.yml no longer caches; docs.yml had id-token: write for Pages OIDC and was the main remaining target. ci.yml is low-impact but dropped for consistency. preview-release.yml runs in fork cache scope (forks cannot write to main's cache) and is unaffected.

Defense-in-depth: moved all ${{ ... }} substitutions in inline shell scripts to env: blocks (GHSL Part 2 pattern), even though upstream values are regex-validated.

What this does NOT close

A compromised dep on the build job can still corrupt dist/. The poisoned artifact would then flow to publish-npm and ship with a valid OIDC token and provenance attestation. Closing this requires a required-reviewer Environment on the publish job — deferred to a follow-up.

Verification

  • All four workflow YAMLs validate.
  • Tests + typecheck + lint all green.
  • Local npm pack produces a 59 KB tarball with the expected contents.

End-to-end verification needs a release-please cycle (open a release PR, merge, watch the two jobs).

…ed workflows

Splits release.yml into two jobs to close the OIDC-theft path that the
TanStack/router compromise (2026-05-11) exploited:

- `build` job: contents: write + pull-requests: write (release-please).
  Runs install/build/pack and uploads the .tgz as an artifact. NO id-token.
- `publish-npm` job: needs build, id-token: write only. Downloads the
  tarball into a scratch dir and runs `npm publish --provenance`. Never
  executes pnpm install or any third-party code.

JSR publish and GH pre-release stay in the build job (JSR uses its own
OIDC binding scoped to JSR, not npm).

Also drops `cache: pnpm` from docs.yml and ci.yml. Per
adnanthekhan.com/2024/05/06/the-monsters-in-your-build-cache, GitHub
Actions cache poisoning lets a compromised dep on a main-branch workflow
steal the cache token and poison entries that other privileged workflows
on main will restore. release.yml never used cache; docs.yml has
id-token: write for Pages OIDC and is the main remaining target. ci.yml
is low impact but dropped for consistency. preview-release.yml runs in
fork cache scope and is unaffected.

All `\${{ ... }}` substitutions in inline shell scripts moved to env:
blocks (GHSL Part 2 defense in depth, even though upstream values are
regex-validated).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mandarini mandarini requested review from a team as code owners May 12, 2026 10:20
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 12, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@supabase/server@62

commit: 592e1b9

@mandarini mandarini merged commit ea17d2f into main May 12, 2026
7 checks passed
@mandarini mandarini deleted the ci/split-publish-job branch May 12, 2026 11:41
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.

2 participants