Proposal: harden the release workflow
@GregoireF ci sta già lavorando.
Dal 25/10/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
Hi! I've been reading through the repository and really like how the release process is set up: trusted publishing with provenance, a guarded workflow_run, Conventional Commit titles enforced on PRs, and a bounded npm range instead of npm@latest. The CONTRIBUTING and ROADMAP docs make the intent very clear.
While going through .github/workflows/ with zizmor 1.31.1, I noticed a few things that could be tightened in the job that publishes to npm. None of them looks exploited or urgent. They are low-cost changes that reduce what a compromised third-party action or dependency could do with the job's OIDC token. I'd be happy to open a PR if you're interested.
What I found
All links point to the current main (dfccb6b).
1. Actions referenced by mutable tags (zizmor unpinned-uses)
https://github.com/modulane/dev-workspace-cli/blob/dfccb6bcd8ccfb32540ed69fa6f13000ec6c231d/.github/workflows/release.yml#L39
https://github.com/modulane/dev-workspace-cli/blob/dfccb6bcd8ccfb32540ed69fa6f13000ec6c231d/.github/workflows/release.yml#L46
These steps run in a job with id-token: write and contents: write. If a tag is moved to a malicious commit, that code runs with the ability to publish to npm. The tj-actions/changed-files incident (March 2025) worked this way. The same applies to ci.yml (including oven-sh/setup-bun@v2) and pr-title.yml. CI gates the release, so its integrity matters too.
2. Package code can run while the OIDC token is available (zizmor adhoc-packages)
npm install --global "npm@^11.5.1"resolves a version from the registry at release time.npm ciruns dependency lifecycle scripts.- In a job with
id-token: write, any step, including those scripts, can request an OIDC token.
The good news is that no package in package-lock.json currently has an install script, so npm ci --ignore-scripts would cost nothing today. The npm bundled with current Node 24 releases should already satisfy ≥ 11.5.1, so the global install could become a version check.
3. The git credential stays on disk (zizmor artipacked)
actions/checkout keeps the contents: write token in .git/config for the whole job, including during npm ci. semantic-release authenticates with GITHUB_TOKEN itself, so persist-credentials: false should be enough.
4. workflow_run trigger (zizmor dangerous-triggers)
To be fair, the event == 'push' and conclusion == 'success' guards make this usage reasonably safe. An alternative would remove both the warning and the head_sha || sha workaround:
release.ymlruns onpush: mainand callsci.ymlas a reusable workflow (uses: $/.github/workflows/ci.yml, the self-repository syntax GitHub added in July 2026);- the release job uses
needs: ci; - tests and publishing then share one run and one commit.
The file would stay release.yml. The provenance on 0.5.0 shows the trusted publisher is bound to that path, so it would keep working.
5. Tests run twice in the release job
https://github.com/modulane/dev-workspace-cli/blob/dfccb6bcd8ccfb32540ed69fa6f13000ec6c231d/.github/workflows/release.yml#L59
https://github.com/modulane/dev-workspace-cli/blob/dfccb6bcd8ccfb32540ed69fa6f13000ec6c231d/package.json#L19
The explicit npm run check step and prepublishOnly both run during a release, after the full CI matrix has already passed on that commit. Dropping the explicit step would keep prepublishOnly as the safety net.
Suggested changes
release.yml
- Permissions:
permissions: {}at workflow level, with each job permission explained in a comment. - Job setup:
- a fork guard and a
main-only condition; timeout-minutes;- job-level
concurrencywithcancel-in-progress: false.
- a fork guard and a
- Install and publish steps:
- checkout with
persist-credentials: false; npm ci --ignore-scriptsfollowed bynpm audit signatures;npx --no-install semantic-release.
- checkout with
- Manual runs:
workflow_dispatchgains an optionaldry-runinput, passed throughenv:rather than interpolated into the script. - Optional:
- an
npmdeployment environment restricted tomain; step-security/harden-runnerin audit mode.
- an
Across all workflows
- Pin every action to a full commit SHA, with a
# vX.Y.Zcomment. - Add
.github/dependabot.ymlfor thegithub-actionsecosystem:- a 7-day cooldown before an update is proposed;
- a
ci:commit prefix, so updates never trigger a release.
- Optionally, add a small zizmor workflow on pull requests to catch regressions.
Docs
Update to match the new flow:
- the "Releases" section of CONTRIBUTING.md;
- the "Release safety" items in ROADMAP.md.
Open questions for you
- Trigger: keep
workflow_run(only pinning and token hygiene), or switch to the reusable-workflow approach? The switch has two side effects:ci.ymlwould no longer run on its own onmain, so the README CI badge would need to point atrelease.yml;- the coverage badge deploy would run inside the release run.
- Environment: would you like an
npmdeployment environment? It is optional, but it lets you scope the trusted publisher on npmjs.com and add protection rules. - Scope: one PR for everything, or one for
release.ymland a separate one for pinningci.ymlandpr-title.ymlplus Dependabot?
Repository settings worth checking
These are only visible to maintainers, so they may already be in place:
- default
GITHUB_TOKENpermissions set to read-only; - full-SHA pinning required for actions;
- a tag ruleset on
v*; - immutable releases;
- after a successful OIDC publish, "Require 2FA and disallow tokens" on the npm package.
Possibly related, not part of this proposal
- Node.js 20 reached end-of-life in April 2026. The CI matrix and
enginesstill include it, andsemantic-release25 (dev dependency) requires Node ≥ 22.14. npm install --global pnpm yarnandsetup-buninstall unpinned tool versions in CI.- A
refs/notes/semantic-release-v1.0.0ref exists on the remote with no matching tag, probably left over from the early releases. It is harmless, but you may want to delete it.
Happy to adjust any of this to how you prefer to work. Just let me know whether a PR would be welcome and which direction you'd like for the trigger.
- Lingua principale
- JavaScript
- Stelle
- 0
- Fork
- 0
- Merge medio
- 7m
- PR unite (30g)
- 6
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di modulane/dev-workspace-cli
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
-
bug
Difficoltà 3/5 1-2 giorni Idoneità per principianti 72/100
Tutte le issue di modulane/dev-workspace-cli
Issue simili
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 85/100
521xueweihan/HelloGitHub#4115 ·
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
outline/outline#14348 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
I maintainer di solito rispondono entro 1 giorno
-
area:install bug needs-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
I maintainer di solito rispondono entro 3 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
I maintainer di solito rispondono entro 1 giorno