ci: harden release pipeline against supply-chain#95
Merged
Conversation
Run semantic-release through Deno instead of npx so the publish tooling resolves from deno.lock under minimumDependencyAge with npm lifecycle scripts disabled — the only code running while id-token:write is active is now pinned and integrity-checked. Drop actions/setup-node, pin every action to a commit SHA, add a top-level contents:read token, disable the shared cache on the publish job, switch installs to `deno ci`, and set minimumDependencyAge. semantic-release is held at ^24 because v25's engines reject Deno's emulated Node. Addresses udibo/udibo#36. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
KyleJune
added a commit
that referenced
this pull request
Jun 14, 2026
@sebbo2002/semantic-release-jsr shell-spawns its own downloaded `deno publish`, and that spawn's args get mangled by Deno's child_process Node-compat layer — so after #95 moved semantic-release onto `deno run`, the publish failed with "unrecognized subcommand". Restore the Node host (actions/setup-node + npx), keeping the supply-chain hardening by pinning every npx package to an exact version (jsr plugin stays 3.2.1). The SHA-pinned actions, contents:read token, and minimumDependencyAge from #95 are unchanged; the semantic-release imports #95 added to deno.json are removed since npx fetches the tooling again. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Hardens the release pipeline against the npm / GitHub Actions supply-chain attack
class (udibo/udibo#36). The publish job is the only one with
id-token: write, sothe goal is that the only code running there is pinned and integrity-checked.
Changes
npx.deno run -A npm:semantic-releaseresolves semantic-release and all pluginsfrom
deno.lockunderminimumDependencyAge, with npm lifecycle scriptsdisabled by default.
npxfetched them fresh and unpinned on every releasewhile
id-token: writewas active — the exact exposure the postmortemdescribes.
actions/setup-nodeis removed (no more node/npm in CI).deno.json: semantic-release^24(v25's engines>=24.10reject Deno's emulated Node24.2.0);@sebbo2002/semantic-release-jsrheld at
3.2.1(4.0.0 is EPLUGINSCONF-broken); plugins pinned via the lockfile.amannn/action-semantic-pull-requestwhich runs in the privilegedpull_request_targettitle check.permissions: contents: readso the non-release jobs drop fromthe default write token; the release job keeps its explicit elevated block.
cache: falseon the publish job's setup-deno — the OIDC job restores noshared cache.
deno ciinstead ofdeno install; documented whypr-title.yml'spull_request_targetis safe (no checkout, no cache, read-only).Trade-off
Release tooling now lives in the workspace
deno.json, sodeno ci/deno installpulls it for all contributors (cached in CI). Kept simple andDeno-native per the issue; a dev/prod split can follow if install weight matters.
Testing
Verified locally on Deno 2.8.2:
deno run -A npm:semantic-release --dry-runloadsall six plugins and correctly no-ops off
main;deno cianddeno task checkpass.