fix(docs): override postcss and sharp past next's vulnerable pins - #309
Merged
Conversation
GSTJ
force-pushed
the
fix/docs-postcss-sharp-advisories
branch
from
July 28, 2026 23:13
e4b0c59 to
8c6a35c
Compare
GSTJ
added a commit
that referenced
this pull request
Jul 29, 2026
#315) Came out of auditing the repo for real vulnerabilities alongside the four Dependabot alerts in #309. The library source is clean. These two are in CI. ## The turbo cache action runs next to NPM_TOKEN on a mutable tag `dtinth/setup-github-actions-caching-for-turbo@v1` is the only third-party action here that isn't `actions/*` or `pnpm/*`. It sits on a personal account and hasn't been pushed to since June 2024. `@v1` is a tag that account can repoint at any time. In `release.yml` it runs at step 6 of the release job. Fourteen steps later the same job writes the npm publish token to `~/.npmrc` in plaintext and runs `pnpm run release`. It also leaves an HTTP server on localhost:41230 alive for the whole job, as the same UID. Whoever controls that tag controls what is running when the publish credentials hit disk, and this pipeline publishes to npm with no human in the loop. In `docs.yml` the same action runs in a job holding `pages: write` and `id-token: write`. Pinned both to `cc723b4600e40a6b8815b65701d8614b91e2669e`, which is v1.3.0 and what `v1` already resolves to, so nothing about the run changes. The 21:05 docs deploy log shows the runner fetching that exact SHA. Left alone: `actions/*` and `pnpm/*` stay on tags. Those are GitHub-owned and pnpm-owned. Pinning them means 25 more `uses:` lines carrying SHAs across 11 distinct actions, and a Renovate PR for every one of them, against a much smaller reduction. ## Any GitHub account can unlock the 45-minute macOS job The e2e approval gate reads the PR's reviews and takes the latest APPROVED or CHANGES_REQUESTED, with no filter on who wrote it: ``` --jq '[.[] | select(.state=="APPROVED" or .state=="CHANGES_REQUESTED")] | sort_by(.submitted_at) | last | .state' ``` This repo is public, so anyone can submit an approving review. Two throwaway accounts, one to open a fork PR and one to approve it, run 45 minutes of `macos-26` on code they wrote. Nothing leaks. I checked whether this is a pwn request and it isn't: GitHub treats `pull_request_review` on a fork PR the same as `pull_request`, so no secrets reach the runner, `GITHUB_TOKEN` is read-only, the job declares `contents: read` and references no secrets, and the caches are scoped to `refs/pull/N/merge`. The cost is billed compute. Added an `author_association` filter for OWNER, MEMBER and COLLABORATOR. An outsider's approval now can't override the owner's CHANGES_REQUESTED, and an outsider's approval on its own leaves the gate closed. Also quoted `"$NPM_TOKEN"` on the `npm config set` line, which clears one shellcheck SC2086. ## Verification - actionlint over all four workflows. Four findings, all pre-existing, none on a line this touches. The SC2086 that was on the `npm config set` line is gone. - the jq filter against four hand-built review lists, covering outsider-overrides-owner, outsider-alone, collaborator, and owner - `v1` dereferences to the pinned SHA, and the last real run fetched the same one  ## Not done here `release.yml` still does `npm config set //registry.npmjs.org/:_authToken "$NPM_TOKEN"`, which leaves the token in `~/.npmrc` for the rest of the job. The env-var placeholder form npm supports would keep it out of the file, but that is the publish path and I'm not changing it in the same session as a release. The pin above removes the vector that made it reachable. Worth doing on its own, with a dry run behind it.
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.
Four Dependabot alerts (#28, #30, #31, #32) all reach us through
nextinapps/docs.next@16.2.12, the latest release, hard-pins"postcss": "8.4.31"and takessharp: "^0.34.5"as an optional dep. Bumping next gets us nowhere, so the fix goes inpnpm.overrides:postcss: ^8.5.23clears GHSA-r28c-9q8g-f849 (needs 8.5.18), GHSA-6g55-p6wh-862q (8.5.12) and GHSA-qx2v-qp2m-jg93 (8.5.10). 8.5.23 was already in the tree for@tailwindcss/postcss, so this dedupes to one copy.sharp: ^0.35.3clears GHSA-f88m-g3jw-g9cj (needs 0.35.0).Rebased onto d1f3353. The lockfile was regenerated from scratch on top of
next16.2.12 (#314) instead of merged, and both overrides are still needed after that bump: 16.2.12 pins the same postcss and the same sharp range 16.2.11 did.No release out of this.
packages/modaldeclares nodependenciesandnpm pack --dry-rungives 4 dist files plus the manifest, so nothing a consumer installs can reach either package. Dependabot filed all four againstpnpm-lock.yaml, which in a workspace covers every app in the repo.Verification
Clean
node_moduleson the rebased branch:postcss@8.5.23andsharp@0.35.3, both above the patch floorsout/, no console errors, no failed requests