Proposal: harden the release workflow
@GregoireF 已经在做这个了。
开始于 2026年10月25日。
评估
这个 Issue 还没有评估数据。
描述
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.
- 主要语言
- JavaScript
- 星标
- 0
- 派生
- 0
- 平均合并
- 7 分钟
- 30 天内合并 PR
- 6
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
modulane/dev-workspace-cli 的其他 Issue
-
bug
难度 2/5 1-3 小时 新手友好度 76/100
-
bug
难度 3/5 1-2 天 新手友好度 72/100
查看 modulane/dev-workspace-cli 的全部 Issue
相似的 Issue
-
bug
难度 2/5 1-3 小时 新手友好度 78/100
glossyio/traffic-monitor#255 ·
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 82/100
juice-shop/juice-shop#3706 ·
维护者通常 1 天内回复
-
Main workflow runs twice for newly created refs可能已有人在做 @rustyconover 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 84/100
duckdb/duckdb-wasm#2293 ·
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 85/100
521xueweihan/HelloGitHub#4115 ·
-
bug
难度 2/5 1-3 小时 新手友好度 68/100
outline/outline#14348 · 1 条评论 ·
维护者通常 1 天内回复