Skip to content

deps: patch js-yaml and brace-expansion DoS advisories - #95

Merged
riglar merged 2 commits into
devfrom
deps/audit-js-yaml-brace-expansion
Jul 27, 2026
Merged

deps: patch js-yaml and brace-expansion DoS advisories#95
riglar merged 2 commits into
devfrom
deps/audit-js-yaml-brace-expansion

Conversation

@riglar

@riglar riglar commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

pnpm audit --audit-level moderate is failing CI on three high advisories (seen on #94's run, but it fails on every branch — the advisories landed 2026-07-24).

Two commits: the dependency fix, plus a one-line CI fix needed to break a merge deadlock (explained at the bottom).

1. deps: the advisories

Advisory Package Fix
GHSA-pm4m-ph32-ghv5 js-yaml 5.2.1 5.2.2
GHSA-mh99-v99m-4gvg brace-expansion 5.0.7 5.0.8 (override range widened)
GHSA-mh99-v99m-4gvg brace-expansion 1.1.16 path removed — see below

js-yaml (exponential parsing time in flow collections) is the one that matters at runtime: js-yaml parses user Maestro flow files, so a malformed flow could hang the CLI. Declared range bumped to ^5.2.2 and a transitive pnpm.overrides guard added alongside the existing 3.x/4.x entries, matching the tar precedent.

brace-expansion (unbounded expansion length → uncatchable OOM) resolved to 5.0.7 under the existing >=3.0.0 <5.0.7 override; widened to <5.0.8.

Why eslint-plugin-import is dropped

The second brace-expansion finding is eslint-plugin-import → minimatch@3 → brace-expansion@1.1.16, and it can't be overridden:

  • Upstream published no 1.x or 2.x backportmaintenance-v1 is still 1.1.16 and maintenance-v2 is 2.1.2, both inside the vulnerable <=5.0.7 range. Only 5.0.8 is patched.
  • Forcing 5.x into that path breaks it: v5 exports { expand }, but minimatch@3 does var expand = require('brace-expansion') and calls it.
  • Overriding minimatch@3 → 10.x breaks differently — minimatch 10's CJS build has no callable default, so eslint-plugin-import's _interopRequireDefault(...)(…) would throw.

eslint.config.cjs registered the plugin with no rules enabled, purely so legacy import/… disable comments resolve, and exactly one such comment was left (src/methods.ts — itself already a dead directive, since neither import/namespace nor new-cap is on). So the plugin is removed along with that half of the comment. That deletes the entire minimatch@3 → brace-expansion@1.x subtree (~1000 lines of lockfile) and avoids adding the GHSA to ignoreGhsas, which would also have silenced the fixable 5.x path.

2. ci: scope the gitleaks scan to the branch under test

The first push here failed secret-scan on bfa2b4c — a commit that is not on this branch. Cause: fetch-depth: 0 fetches refs/heads/* (every branch) and gitleaks git scans all reachable commits, not just the checked-out ref. #94 pins two KEK public keys and allowlists them in the same branch, so it fails every other branch's scan, which is judged against the allowlist at its own tip.

That is a hard deadlock, since secret-scan and lint-and-test are both required checks on dev:

--log-opts=HEAD limits the scan to commits reachable from what's checked out — the full history of the branch, or of the PR merge commit (base + PR commits). Coverage is unchanged in the way that matters: every commit of the branch under test is still scanned, each branch is still fully scanned by its own PR, and pushes to dev/production still scan their full history.

Verified with the pinned gitleaks 8.30.1 locally:

  • scoped to this branch → 61 commits, no leaks
  • scoped to feat/binary-envelope-encryption using this branch's allowlist → the same 2 findings still fire

So the change narrows which commits are in scope without weakening detection. (--config=/dev/null was my first sanity check and was invalid — an empty config disables the ruleset, so it reports clean regardless.)

Notes

Verification

pnpm install --frozen-lockfile ✅ (the flag CI uses) · pnpm audit --audit-level moderate ✅ exit 0, only the pre-existing ignored moderate · pnpm lint ✅ · pnpm typecheck ✅ · pnpm build ✅ · pnpm test ✅ 167 passing · CI lint-and-test ✅ green on the first push

🤖 Generated with Claude Code

`pnpm audit --audit-level moderate` was failing CI on three high
advisories:

- js-yaml 5.2.1 -> 5.2.2 (GHSA-pm4m-ph32-ghv5): exponential parsing time
  in flow collections. This one is reachable at runtime — js-yaml parses
  user Maestro flow files. Bumped the declared range and added a
  transitive override guard alongside the existing 3.x/4.x entries.
- brace-expansion 5.0.7 -> 5.0.8 (GHSA-mh99-v99m-4gvg): unbounded
  expansion length causing an uncatchable OOM crash. Widened the
  existing override range.
- brace-expansion 1.1.16, reached via eslint-plugin-import -> minimatch@3.
  Upstream published no 1.x or 2.x backport (maintenance-v1 is still
  1.1.16, maintenance-v2 2.1.2 — both inside the vulnerable <=5.0.7
  range), and 5.x cannot be forced into that path: v5 exports
  `{ expand }` while minimatch@3 requires a callable default. Overriding
  minimatch@3 -> 10.x breaks differently, since its CJS build has no
  callable default for eslint-plugin-import's interop require.

So eslint-plugin-import is dropped instead. eslint.config.cjs registered
it with no rules enabled — purely so legacy `import/...` disable comments
resolve — and exactly one such comment remained (src/methods.ts, itself
already a dead directive since neither `import/namespace` nor `new-cap`
is enabled). Removing the plugin deletes the whole
minimatch@3 -> brace-expansion@1.x subtree and avoids adding the GHSA to
`ignoreGhsas`, which would also have silenced the fixable 5.x path.

No other dependency resolutions change. The remaining ignored moderate
(@hono/node-server, GHSA-frvp-7c67-39w9) is unchanged — the MCP SDK is
already at its latest release, so there is no fix to take.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Jul 26, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

`fetch-depth: 0` fetches refs/heads/* — every branch — and `gitleaks git`
scans all reachable commits, not just the checked-out ref. So a branch
that legitimately commits a high-entropy value together with its own
.gitleaks.toml allowlist entry fails the secret-scan of every OTHER
branch, because those are judged against the allowlist at their own tip.

That is currently a hard deadlock. feat/binary-envelope-encryption (#94)
pins two KEK public keys and allowlists them in the same branch, so any
PR branched from dev fails secret-scan on commit bfa2b4c, while #94
itself cannot merge until it picks up this branch's `pnpm audit` fix.

--log-opts=HEAD limits the scan to commits reachable from what is checked
out: the full history of the branch, or of the PR merge commit (base +
PR commits). Coverage is unchanged in the way that matters — every commit
of the branch under test is still scanned, each branch is fully scanned
by its own PR, and pushes to dev/production scan their full history.

Verified with the pinned gitleaks 8.30.1: scoped to this branch, 61
commits, no leaks; scoped to feat/binary-envelope-encryption with this
branch's allowlist, the same 2 findings still fire — so the scoping
narrows which commits are in scope without weakening detection.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@riglar
riglar merged commit a4f11ff into dev Jul 27, 2026
8 checks passed
@riglar
riglar deleted the deps/audit-js-yaml-brace-expansion branch July 27, 2026 08:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant