Skip to content

ci: stage npm releases and skip install scripts in publish jobs - #91

Open
mislavivanda wants to merge 1 commit into
mainfrom
ci/npm-publish-hardening
Open

mislavivanda wants to merge 1 commit into
mainfrom
ci/npm-publish-hardening

Conversation

@mislavivanda

@mislavivanda mislavivanda commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Harden every npm release job that holds id-token: write:

  • install dependencies with npm ci --ignore-scripts, preventing dependency lifecycle scripts from minting the job's OIDC token
  • replace direct npm publish with npm stage publish --provenance --access public
  • apply the validated script-free install to the matching PR-check jobs
  • document the maintainer approval step without changing the PyPI release flow

The threat is the combination of dependency install scripts and id-token: write: a compromised install script can request the GitHub OIDC token and publish a package with valid provenance. Staged publishing also removes CI's ability to make a version live without a maintainer's 2FA approval.

Per-job changes and local verification

npm package Release install/build/pack with --ignore-scripts Matching PR checks Decision
@daytona/n8n-nodes-daytona Pass: npm ci --ignore-scripts, npm run build --if-present, npm pack --dry-run Pass: lint + build Keep --ignore-scripts. isolated-vm is present transitively through n8n-workflow, but n8n-node build and packaging do not need its native install artifact; no targeted rebuild is needed.
@daytona/pi Pass: install, optional build, dry-run pack Pass: typecheck + optional build Use --ignore-scripts.
@daytona/opencode Pass: install, build, dry-run pack Pass: typecheck + build Use --ignore-scripts.
@daytona/convex Pass: install, build, dry-run pack Pass: typecheck + build + 50 unit tests Use --ignore-scripts; the release build is only tsc.
@daytona/claude-toolsets Existing release job already used --ignore-scripts; only the publish command changes Existing CI job already uses --ignore-scripts Preserve the existing hardened recipe.

The n8n RELEASE_MODE=true behavior remains intact. npm 12's npm stage publish --dry-run was also checked locally and did invoke prepublishOnly / n8n-node prerelease, so staged publishing preserves that package's release hook.

/home/opencode/go/bin/actionlint .github/workflows/release.yml .github/workflows/ci.yml passes.

Staged publishing flow

Merging an npm package's Release PR now stages its version with provenance rather than making it live. A maintainer reviews and approves it with 2FA either at npmjs.com → package → Staged Packages, or via:

npm stage list
npm stage approve <id>

npm stage publish requires npm >= 11.15.0 and Node >= 22.14.0. actions/setup-node with lts/* currently resolves to Node 24.21.0, and every npm publish job runs npm install -g npm@latest (currently npm 12.2.0). The stage command supports both --access public and --provenance; provenance is generated with the staged artifact in CI and is present when that artifact is approved.

OWNER CHECKLIST

Quick check before this PR merges

npm's current trusted-publisher docs state that npm stage publish is always allowed for every trusted publisher; the allowed-actions setting only controls the additional direct npm publish and npm dist-tag rights (docs, "Allowed actions"). The note about configurations created before May 20, 2026 being "npm publish only" describes how the direct-publish right was migrated; it does not remove staging. So no config should need editing before merge, but because a wrong assumption here fails the next release, confirm it on each package's npmjs.com → Settings → Trusted publishing page (the "Allowed actions" section should read "npm stage publish is always allowed"):

  • @daytona/n8n-nodes-daytona
  • @daytona/pi
  • @daytona/opencode
  • @daytona/convex
  • @daytona/claude-toolsets (already confirmed when it was created on 2026-10-08)

If an older package's page does not show staging as allowed, delete and recreate that connection with the same fields (daytona/integrations, release.yml, environment npm) before merging. If a release does fail authentication, fix the config and re-run the failed job; no new release is needed.

After stage access is confirmed (may be done immediately after merge)

For all five npm packages, untick/disable direct npm publish on the trusted publisher while leaving npm stage publish allowed:

  • @daytona/n8n-nodes-daytona
  • @daytona/pi
  • @daytona/opencode
  • @daytona/convex
  • @daytona/claude-toolsets

That owner-only setting ensures the workflow identity can stage but can never bypass maintainer review and 2FA approval.

npm documentation

FYI @aprojic, who raised the install-script/OIDC issue.

This touches the release.yml area near draft #90's release-workflow restructure. Whichever PR merges second will need a trivial rebase.


Summary by cubic

Npm release jobs now stage versions for maintainer review and 2FA approval instead of publishing live, and all publish jobs run npm ci --ignore-scripts so dependency lifecycle scripts can't mint the workflow's GitHub OIDC token. The same hardened install applies to the matching PR-check jobs, and the README documents the staged-publishing flow; provenance is generated at stage time, and release hooks like n8n's prepublishOnly still run.

Migration

  • Before merge, add npm stage publish to the GitHub Actions trusted publisher for @daytona/n8n-nodes-daytona, @daytona/pi, @daytona/opencode, and @daytona/convex; configs created before May 20, 2026 only allow npm publish. If the existing connection can't be edited, delete and recreate it with stage permission.
  • After merge, disable direct npm publish on the trusted publisher for all five packages so the workflow identity can only stage.

Written for commit 4cc587f. Summary will update on new commits.

View guided diff Turn on auto-fix

Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
@mislavivanda
mislavivanda requested a review from a team as a code owner October 8, 2026 21:34

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

This PR changes infrastructure or deployment configuration. Ultrareviews find 2.4x more serious bugs than standard reviews. Comment @cubic-dev-ai ultrareview to run one.

View guided diff | Turn on auto-fix | Re-trigger cubic

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.

2 participants