ci: harden GitHub Actions workflows - #1052
Open
EhabY wants to merge 2 commits into
Open
Conversation
- Add least-privilege permissions blocks at workflow and job level so jobs only receive the scopes they need (contents: read by default, write only where releases are created). - Set persist-credentials: false on all actions/checkout steps that do not push, so the repo-scoped token is not left on disk for later steps and node_modules scripts. - pre-release: verify the release tag commit is an ancestor of origin/main before building, preventing releases from tags pointing at unreviewed commits. - publish-extension: gate marketplace publish jobs behind a 'publish' environment, pin vsce and ovsx to exact versions instead of installing latest at run time, and pass marketplace PATs via env vars instead of argv (argv is world-readable via /proc on the runner).
Pre-release tags are intentionally used to test builds without merging everything to main first, so drop the ancestor check and full fetch; stable release.yaml keeps its existing tag-on-main verification.
EhabY
force-pushed
the
ci/supply-chain-hardening
branch
from
July 29, 2026 16:02
75892d1 to
f6ec3b7
Compare
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.
Hardens the GitHub Actions release/publish pipeline. No runtime extension code is touched, and no workflow behavior changes on today's happy path (details below).
Least-privilege token permissions
ci.yaml: adds a top-levelpermissions: contents: readblock (previously inherited the default, potentially write-all, token).release.yaml/pre-release.yaml: workflow-level permissions downgraded tocontents: read; only thepublishjob getscontents: write+pull-requests: read— the same scopes the whole workflow had before, now confined to the job that creates the release.actions/checkoutsteps that do not push now setpersist-credentials: false, so the repo-scoped token is not left in.git/configwhere later steps andnode_moduleslifecycle scripts can read it.Publish pipeline
publish-extension.yaml: the Marketplace/OpenVSX publish jobs now run in apublishenvironment, andvsce/ovsxare pinned (@vscode/vsce@3.9.2,ovsx@1.0.2) instead of installing whatever is latest at run time. Both pins are exactly today'slatest, and 3.9.2 is also the version the lockfile already uses forvsce package, so packaging and publishing now run the same tool version.VSCE_PAT/OVSX_PATenv vars instead of-p <token>argv, which is world-readable via/procon the runner. Verified both pinned versions read these env vars natively (vsce3.9.2 defaults--patfromprocess.env.VSCE_PAT;ovsx1.0.2addEnvOptionsreadsOVSX_PAT).Important
Admin follow-up required: the
publishenvironment is auto-created on first run with no protection rules (so it does not block anything by itself). A repo admin should add required reviewers to it and ideally moveVSCE_PAT/OVSX_PATfrom repo secrets into environment secrets so they are only exposed to approved publish runs.Why this is behavior-neutral
GITHUB_TOKENexcept the GitHub-release job, which keepscontents: write+pull-requests: read(needed bysoftprops/action-gh-release+generate_release_notes). Reusable-workflow permission inheritance checked: every called job requests a subset of what its caller grants.git push/fetchafter checkout, so dropping persisted credentials is inert. Thegithub:coder/coder#v2.34.1catalog dependency is cloned by pnpm in its own store directory, which never saw the checkout's repo-local credential config — it is an anonymous https clone of a public repo before and after.release.yaml's existing tag-on-main verification only needs the refs already fetched byfetch-depth: 0; no network/auth involved.publishenvironment adds a Deployments record and nothing else until protection rules are configured.Not included
main(used for testing without merging); stablerelease.yamlkeeps its existing tag-on-main check.pnpm auditfindings in dev-only transitive dependencies (diff,serialize-javascript,brace-expansionvia mocha/@vscode/test-cli) are deliberately not addressed here: they are test-runner-only and unreachable from the shipped extension.