Skip to content

Investigate NPM Trusted Publishing via CircleCI for Automatically Published Monorepo Packages #33591

@AtofStryker

Description

@AtofStryker

Investigate NPM Trusted Publishing via CircleCI for Automatically Published Packages

Background

NPM Trusted Publishers is a security feature that allows CI/CD pipelines to publish packages to npm without long-lived authentication tokens. Instead, it uses OpenID Connect (OIDC) to exchange short-lived, scoped tokens at publish time — eliminating the need to store NPM_TOKEN as a secret in CircleCI.

As of April 2026, CircleCI is now a supported trusted publisher for npm, joining GitHub Actions. This opens the door for cypress-io/cypress to adopt this more secure publishing model.

References:


Problem

Currently, publishing packages from this monorepo relies on a long-lived NPM_TOKEN stored as a CircleCI environment variable/secret. This approach carries several risks:

  • Token exposure: Long-lived tokens can be leaked through logs, compromised secrets stores, or supply chain attacks.
  • Broad scope: A single token grants publish access to all packages and is not scoped to specific workflows or conditions.
  • No automatic expiry: Tokens do not expire and must be manually rotated.
  • Auditability gaps: It's harder to trace exactly which CI job triggered a publish.

Goal

Investigate and implement NPM Trusted Publishing (OIDC-based) for all automatically published packages in this monorepo, so that:

  • No long-lived NPM tokens need to be stored in CircleCI secrets.
  • Publish access is scoped to specific CircleCI workflows/jobs/branches (e.g., release pipelines on main).
  • The attack surface for supply chain compromise is significantly reduced.

Automatically Published Packages

The following packages in this monorepo are published to npm automatically via CircleCI and are in scope for this investigation:

@cypress/*

Package npm
@cypress/angular https://www.npmjs.com/package/@cypress/angular
@cypress/angular-zoneless https://www.npmjs.com/package/@cypress/angular-zoneless
@cypress/eslint-plugin-dev https://www.npmjs.com/package/@cypress/eslint-plugin-dev
@cypress/grep https://www.npmjs.com/package/@cypress/grep
@cypress/mount-utils https://www.npmjs.com/package/@cypress/mount-utils
@cypress/puppeteer https://www.npmjs.com/package/@cypress/puppeteer
@cypress/react https://www.npmjs.com/package/@cypress/react
@cypress/schematic https://www.npmjs.com/package/@cypress/schematic
@cypress/svelte https://www.npmjs.com/package/@cypress/svelte
@cypress/vite-dev-server https://www.npmjs.com/package/@cypress/vite-dev-server
@cypress/vite-plugin-cypress-esm https://www.npmjs.com/package/@cypress/vite-plugin-cypress-esm
@cypress/vue https://www.npmjs.com/package/@cypress/vue
@cypress/webpack-batteries-included-preprocessor https://www.npmjs.com/package/@cypress/webpack-batteries-included-preprocessor
@cypress/webpack-dev-server https://www.npmjs.com/package/@cypress/webpack-dev-server
@cypress/webpack-preprocessor https://www.npmjs.com/package/@cypress/webpack-preprocessor

Investigation Tasks

  • Audit current publish workflow: Identify all CircleCI jobs that publish to npm (look for npm publish calls and NPM_TOKEN usage across .circleci/ config).
  • Confirm package ownership on npm: Verify that the npm organization (cypress / @cypress) account can configure Trusted Publishers per-package via the npm web UI or API.
  • Understand OIDC config for CircleCI: Review CircleCI's OIDC token documentation and determine what claims (org slug, project ID, workflow name) are available to use as trust constraints.
  • Design trust policy: Define the CircleCI workflow/job conditions that should be trusted to publish (e.g., only the release workflow on main, triggered by a specific pipeline/tag).
  • Configure Trusted Publishers on npm: For each package in scope, add CircleCI as a trusted publisher with the appropriate claim constraints in the npm package settings.
  • Update CircleCI config: Update the publish job(s) to use OIDC token exchange instead of NPM_TOKEN. CircleCI provides an OIDC token via $CIRCLE_OIDC_TOKEN; npm's --provenance and OIDC flows need to be wired up accordingly.
  • Remove NPM_TOKEN secret: Once verified in a dry run / staging publish, remove the NPM_TOKEN secret from CircleCI project/org settings. (NOTE: verify other repos possibly using the organization context!)
  • Test end-to-end: Validate that a release pipeline successfully publishes at least one package using the new OIDC flow.
  • Document the new process: Update internal documentation and calendars to reflect the change.

Security Benefits

  • ✅ No long-lived npm tokens stored as CI secrets
  • ✅ Tokens are short-lived and scoped to the specific CircleCI job
  • ✅ npm audit logs clearly identify the trusted publisher that performed each publish
  • ✅ Accidental token leaks in logs or compromised secrets no longer grant publish access
  • ✅ Aligns with npm's recommended best practice for automated publishing

Acceptance Criteria

  • All automatically published packages in this monorepo use OIDC-based trusted publishing via CircleCI.
  • NPM_TOKEN is no longer required in CircleCI secrets for any publish job.
  • The CircleCI release pipeline successfully publishes packages end-to-end without a stored npm token.
  • Trust constraints are scoped to the release workflow only (not all jobs/branches).
  • Updated documentation reflects the new publish process.
  • Remove NPM_TOKEN schedule from engineering calendar and documentation

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions