Skip to content

Harden the release workflow #4

Closed

Description

@TimG1804

Some hardening for .github/workflows/build-release-changelog.yml. It publishes to npm with NPM_TOKEN, so it's worth tightening:

  • Third-party actions are pinned to mutable tags — mikepenz/release-changelog-builder-action@v4, ncipollo/release-action@v1. Pin to a commit SHA so the tag can't be moved under us.
  • npm ci runs lifecycle scripts in the same job that has the publish token. npm ci --ignore-scripts would cut that off (build is a plain rollup run and doesn't need them).
  • Classic NPM_TOKEN. npm supports OIDC trusted publishing now — no long-lived secret to rotate, and releases get provenance. Needs id-token: write.
  • permissions: contents: write is job-wide. Only the release step needs it.
  • node-version: '20' is end of life. The build runs fine on 24.

None of this is urgent on its own, but the token makes the job a worthwhile target.

Activity

  1. TimG1804 commented on Aug 20, 2026

    @TimG1804
    CollaboratorAuthor

    SHA pinning, --ignore-scripts, Node 24 and the permissions: {} default are in #11.

    Left open for the OIDC switch: that needs a trusted publisher configured for the package on npmjs.com, which has to be done by a maintainer there. --provenance on top of it also needs the repository field from #9.

  2. TimG1804 commented on Aug 20, 2026

    @TimG1804
    CollaboratorAuthor

    Concrete evidence for the OIDC part: the v0.1.2 release run failed at the publish step.

    npm error code E404
    npm error 404 Not Found - PUT https://registry.npmjs.org/@3m5-de%2fsquirrel-select - Not found
    

    The package exists and 0.1.1 is on latest, so this is npm answering an unauthenticated publish with 404 rather than 401. gh secret list shows NPM_TOKEN was last set on 2024-02-08, and npm has retired classic tokens since.

    So the token has to be replaced either way — which makes trusted publishing the better thing to set up instead of minting another secret.

  3. TimG1804 commented on Aug 20, 2026

    @TimG1804
    CollaboratorAuthor

    Correction to my earlier comment: I called the token expired, which is not established. A rejected credential normally surfaces as E401; the E404 seen here fits "authenticated but not authorised to write this package" at least as well. The secret is present and non-empty in the job log, and this same value published 0.1.1.

    So the case for trusted publishing here is the structural one rather than "the token expired": the package has a single maintainer (robert-heinig), and a company-sponsored package depending on one persons account and one long-lived secret is what makes a release stall like this. Diagnosis details in #16.

  4. TimG1804 commented on Aug 20, 2026

    @TimG1804
    CollaboratorAuthor

    Cause is confirmed now, see #16: the token was killed by npm's classic token revocation on 2025-12-09, and a revoked token does produce E404 on a scoped publish. My previous comment doubting that was wrong.

    Does not change the direction here, but sharpens it: a replacement granular token caps at 90 days and loses direct publishing in January 2027, so trusted publishing is the only path worth the setup. Note it needs npm CLI >= 11.5.1, which the Node 24 bump from #12 already provides.

  5. TimG1804 commented on Sep 18, 2026

    @TimG1804
    CollaboratorAuthor

    All five points are in place:

    The split is verified by inspection only; the workflow runs on tag push, so
    it is first exercised for real at the next release.

    Repository-side hardening added alongside this: secret scanning with push
    protection, Dependabot security updates, private vulnerability reporting,
    SECURITY.md, branch protection on main with a required build check,
    and a ruleset preventing v* tags from being deleted or force-moved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity issue or hardening

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions