fix(security): patch fast-uri, postcss, and brace-expansion advisories - #1510
Conversation
Resolve the two open Dependabot alerts plus a third high-severity advisory the repo's own audit surfaces but Dependabot had not filed, all via version-ranged pnpm overrides (they lapse once the upstream tree moves past them): - fast-uri 3.1.4 -> 3.1.5 (website): GHSA-7p8r-x3mc-p8w7, high. Host confusion via backslash authority introducer. Pulled in transitively by ajv@8.18.0; bounded to ^3.1.5 so it stays on the 3.x line ajv expects. - postcss 8.5.22 -> 8.5.25 (root): GHSA-fxqj-rqcc-2cmp, moderate. Arbitrary .map file read via attacker-controlled sourceMappingURL. Pulled in by vite (dev/test tooling). - brace-expansion 5.0.8 -> 5.0.9 (website): GHSA-rgw5-rvv9-x895, high. DoS via unbounded recursion. The existing override capped at >=5.0.8, and 5.0.8 is itself vulnerable under this newer advisory; the root already resolved to 5.0.9. Root and website audits are clean at --audit-level high (and any-severity for the website). Full test suite: 3662 passing.
📝 WalkthroughWalkthroughDependency overrides, CI permissions, website lockfile validation, and the Nix dependency hash were updated. Archive comments now document race detection and rollback safeguards. No executable archive behavior or public declarations changed. ChangesDependency and CI maintenance
Archive race-safety documentation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying openspec-docs with
|
| Latest commit: |
9b26cc8
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://a3a21f83.openspec-docs.pages.dev |
| Branch Preview URL: | https://claude-fix-security-alerts-a.openspec-docs.pages.dev |
…ockfile drift check, document archive TOCTOU intent Hardening pass over the security fixes, from a parallel review of the dependency, CI, archive, and adjacent-code surfaces. Each item is low-risk and verified; resolved dependency versions are unchanged. - deps: bound the three security overrides to their current major (brace-expansion ">=5.0.9 <6", postcss ">=8.5.23 <9"). A bare ">=X" pin would take a future major on the next lockfile regen without review; the website already models the caret-bounded idiom. - ci: scope release-prepare.yml permissions per job. The top-level block dropped "pull-requests: write"; only the "prepare" job (which opens the Version Packages PR) now holds it. The "beta" job only tags/releases and publishes via OIDC, so it inherits the narrower default (least privilege). - ci: add a "Website Lockfile Drift" job to security.yml. The website keeps its own lockfile and is never installed in CI, so a website override that stops resolving would go unnoticed and `pnpm audit` would scan a stale graph. A `pnpm install --frozen-lockfile --ignore-scripts --dir website` fails fast on that drift (root drift is already caught in ci.yml). - archive: add intent comments at the 7 js/file-system-race sites in src/core/archive.ts. The stat->read->re-stat pattern is a deliberate concurrent-change detector; the comments record why, so no future refactor (human or scanner-driven) collapses it to fd I/O and blinds the guard. Verified: 3662 tests pass, build clean, website build clean, root+website audits clean at --audit-level high, and the new frozen-lockfile check passes locally.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@flake.nix`:
- Line 54: Update the pnpm dependency hash in flake.nix by running
./scripts/update-flake.sh, then replace lib.fakeHash in the pnpmDeps
configuration with the returned sha256-... value and commit the resulting
flake.nix change.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 29a7a7bd-1db0-4c9c-818b-49833b47c14e
⛔ Files ignored due to path filters (2)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlwebsite/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (6)
.github/workflows/release-prepare.yml.github/workflows/security.ymlflake.nixpackage.jsonsrc/core/archive.tswebsite/package.json
🚧 Files skipped from review as they are similar to previous changes (2)
- website/package.json
- package.json
The root pnpm-lock.yaml changed (postcss + brace-expansion overrides), which stales the fixed-output pnpmDeps hash and fails Nix Flake Validation. Repin to the value CI computed from the new lockfile.
9b26cc8 to
4e509f4
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
alfred-openspec
left a comment
There was a problem hiding this comment.
Exact-head dependency and workflow review is clean. The installed trees resolve brace-expansion 5.0.9, postcss 8.5.25, and fast-uri 3.1.5 with no vulnerable copies; fresh root and website frozen installs, all audits, the root build, 208 archive tests, and the website production build pass. Release permissions are correctly scoped, the website drift check is pinned and read-only, and the full hosted matrix including Nix is green.
Status
Ready. Fixes every open Dependabot alert (plus one high-severity advisory Dependabot had not filed) at the root. The 10 open CodeQL alerts are triaged with a documented disposition below — they are not exploitable in OpenSpec's threat model, and none has a code fix that doesn't degrade the tests or defeat the archive engine's deliberate concurrency guard.
Dependency alerts — fixed
ajv@8.18.0fast-uri@<3.1.5→^3.1.5vite(test tooling)postcss@<8.5.23→>=8.5.23minimatch@3brace-expansion@<=5.0.8→>=5.0.9What was wrong: three vulnerable transitive dev-dependencies.
fast-uriandpostcssare the two open Dependabot alerts. Thebrace-expansionone is not in the Dependabot list, but the repo's own website audit already fails on it onmain(2 high before this change) — the previous override capped at>=5.0.8, and 5.0.8 is itself vulnerable under this newer advisory.How it was fixed: version-ranged
pnpm.overrides, matching the pattern already in the repo. Each range lapses automatically once the upstream tree moves past it.fast-uriis bounded to^3.1.5(stays on the 3.x lineajvexpects) rather than the unbounded>=3.1.5, which resolved to a 4.x major.Proof:
pnpm audit --prod --audit-level high(root) → cleanpnpm audit --audit-level high(root, all deps) → cleanpnpm audit --audit-level high --dir website→ clean (and clean at any severity)websiteproduction build (static export) → cleanCode-scanning alerts — triaged, documented risk-acceptance
All 10 open alerts are
js/file-system-race(CWE-367, TOCTOU). None is exploitable here and none has a non-degrading code fix:openspec archiveis an unprivileged CLI operating on the user's own files with the user's own permissions. No boundary is crossed.src/core/archive.tssit inside the rollback / concurrent-change-detection engine (fingerprintPath,releaseArchiveClaim,restoreSpecSnapshots, …). That code intentionally does stat → read → re-stat by name and then throws"Path changed while archive was reading …"/"rollback would overwrite a concurrent change". The flagged pattern is a deliberate race detector. Rewriting it to a pinned file descriptor would blind exactly the detection it exists to perform — strictly worse.mkdtemptemp dirs (asserting inode preservation / file mode / content). There is no attacker and no untrusted path; a file-descriptor rewrite would only make the assertions less readable.CodeQL runs via GitHub default setup (no workflow file in-repo), so a committed
paths-ignoreto descope test code isn't available. Disposition: dismiss the 10 as won't fix — not exploitable in this threat model; concurrent-change already guarded (7 archive) and used in tests (3 test), with this write-up as the justification.Notes
brace-expansionbump also forcesminimatch@3's copy to 5.0.9 (the previous override already forced it to 5.0.8, i.e. the 5.x line). Verified harmless:minimatch@3reaches the website only viaserve-handler(dev preview, no brace-pattern globs), and the production build passes.brace-expansionfix is beyond the literal Dependabot list but is a real high-severity advisory the CI audit catches; leaving it would keepmain's Security workflow red.Hardening pass (commit
harden(security): …)A parallel review of four surfaces (dependency, CI, archive engine, adjacent code) produced these low-risk additions. Resolved dependency versions are unchanged.
brace-expansion ">=5.0.9 <6",postcss ">=8.5.23 <9")>=Xpin would take a future major on the next lockfile regen without review; the website already used the caret-bounded idiomrelease-prepare.ymlpull-requests: writefrom the top-level block; only thepreparejob (opens the Version Packages PR) keeps it. Thebetajob only tags/releases + publishes via OIDC — least privilegeWebsite Lockfile DriftCI jobpnpm auditwould scan a stale graph.pnpm install --frozen-lockfile --ignore-scripts --dir websitefails fast on drift (root drift is already caught inci.yml)js/file-system-racesites insrc/core/archive.tsThe review also confirmed as already-solid (nothing added): Dependabot covers all three surfaces, npm provenance is live, the
filesallowlist ships no source/secrets,postinstallis inert, every Action is SHA-pinned, no script-injection, and the injection/traversal/prototype-pollution surface is guarded. An independent trace of the archive rollback path found no constructible data-loss or symlink-escape exploit.Nix: the root lockfile change staled
flake.nix'spnpmDepshash; repinned to the value CI computed. All checks green.