Skip to content

fix(deps): bump brace-expansion to patched versions for CVE-2026-13149 - #10

Merged
ashirman merged 3 commits into
mainfrom
fix/cve-2026-13149-brace-expansion
Jul 30, 2026
Merged

fix(deps): bump brace-expansion to patched versions for CVE-2026-13149#10
ashirman merged 3 commits into
mainfrom
fix/cve-2026-13149-brace-expansion

Conversation

@revopushbot

Copy link
Copy Markdown
Contributor

Summary

Resolves CVE-2026-13149 / GHSA-3jxr-9vmj-r5cpbrace-expansion: DoS via exponential-time expansion of consecutive non-expanding {} groups.

brace-expansion was resolving to 1.1.15 (transitively via minimatch@3) and 2.1.1 (via minimatch@9), both within the vulnerable ranges.

Approach — lockfile only

Every existing transitive range already admits a patched release, so this is a pure lockfile re-resolve (npm update brace-expansion --package-lock-only, which keeps yarn.lock in sync). No overrides / resolutions pin was needed in package.json — unlike the previous uuid fix (#9), nothing here required forcing a version outside its declared range.

range consumer before after
^1.1.7 minimatch@3 1.1.15 ❌ 1.1.17
^2.0.2 minimatch@9 2.1.1 ❌ 2.1.3
^5.0.5 minimatch@10 5.0.7 5.0.8

Patched versions per the advisory: 1.1.16, 2.1.2, 5.0.7.

Only package-lock.json and yarn.lock change.

Verification

  • npm audit no longer reports GHSA-3jxr-9vmj-r5cp.
  • yarn install --frozen-lockfile succeeds; installed tree confirmed at 1.1.17 / 2.1.3 / 5.0.8.
  • yarn build (expo-module build) passes.

Out of scope — still open

  1. CVE-2026-14257 / GHSA-mh99-v99m-4gvg — a different brace-expansion DoS. Vulnerable range is <=5.0.7 and it is first patched only in 5.0.8, so the 1.x and 2.x lines have no patched release at all. Clearing it would mean force-overriding every consumer to 5.0.8, crossing four majors for minimatch@3/@9 — worth validating on its own rather than folding in here.
  2. postcss <=8.5.17 (GHSA-r28c-9q8g-f849) — unrelated; a non-breaking lockfile bump to 8.5.25 is available.

🤖 Generated with Claude Code

brace-expansion was resolving to 1.1.15 (via minimatch@3) and 2.1.1
(via minimatch@9), both flagged by CVE-2026-13149 / GHSA-3jxr-9vmj-r5cp
(DoS via exponential-time expansion of consecutive non-expanding {}
groups), fixed in 1.1.16, 2.1.2 and 5.0.7 respectively.

All existing transitive ranges (^1.1.7, ^2.0.2, ^5.0.5) already admit a
patched release, so this is a lockfile-only re-resolve -- no overrides
or resolutions pin needed in package.json.

  ^1.1.7  1.1.15 -> 1.1.17
  ^2.0.2  2.1.1  -> 2.1.3
  ^5.0.5  5.0.7  -> 5.0.8

Verified: CVE-2026-13149 no longer reported by npm audit;
yarn install --frozen-lockfile and expo-module build both pass.

Note: the unrelated CVE-2026-14257 / GHSA-mh99-v99m-4gvg (vulnerable
range <=5.0.7, first patched only in 5.0.8) still flags the 1.x and 2.x
lines, which have no patched release for it. Clearing that one needs a
forced override across four majors of minimatch and is tracked
separately.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
revopushbot and others added 2 commits July 29, 2026 22:07
Adds .github/workflows/CI.yaml with two jobs, `check` (npm ci +
npm run build) and `lint` (npm ci + npm run lint), running on PRs
targeting main. Mirrors the code-push-server/cli workflow: SHA-pinned
actions, least-privilege `contents: read`, and concurrency cancellation.

Node is pinned to 20.19.4 rather than 20.19.0: the strictest engines
constraint in the tree is react-native's
`^20.19.4 || ^22.13.0 || ^24.3.0 || >=25.0.0`, which 20.19.0 does not
satisfy.

Repairing lint, which was broken before this change:

- Add eslint.config.js (flat config). expo-module-scripts now ships
  ESLint 9, which ignores the legacy .eslintrc.js and failed with
  "couldn't find an eslint.config.(js|mjs|cjs) file". .eslintrc.js is
  kept because it is a non-optional expo-module-scripts template and is
  recreated by `expo-module prepare` on every install; ESLint 9 ignores
  it once a flat config is present. eslint.config.js is an optional
  template, so prepare keeps it in sync rather than clobbering it.

- Declare eslint and prettier as devDependencies. Both are peers of
  eslint-config-universe with the open-ended ranges `>=8.10` and `>=3`.
  npm 7+ auto-installs peers (resolving eslint 9.39.4), but yarn 1 does
  not, so under yarn nothing provided eslint and `npx eslint` silently
  downloaded 10.8.0 -- which does not expose `eslint/config` and crashed
  the flat config. Pinning them makes npm and yarn agree and keeps CI
  from drifting onto a future ESLint major.

Verified on Node 20.19.4: `npm ci`, `npm run build` and `npm run lint`
all exit 0, as does `yarn lint`. Lint currently reports 192
prettier/prettier warnings (0 errors) in src/withRevopush.ts; these do
not fail the build and are left for a separate formatting-only change to
avoid conflicting with the in-flight feature branches.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The previous layout ran `check` and `lint` as two jobs. Jobs do not share
a filesystem -- each gets its own runner -- so the split meant checking
out the repo twice and running `npm ci` twice. The install dominates
runtime here (~40s versus a few seconds for build and lint combined), so
the second job roughly doubled CI minutes to run one extra command.
Collapsed into one `check` job with Build and Lint as sequential steps.

Lint is guarded with `if: ${{ !cancelled() }}` so a build failure still
reports the lint result instead of hiding it behind another push.

Also:
- Add a `push: [main]` trigger, so a broken main is visible even when a
  PR merges cleanly but the merge result does not build.
- Key `concurrency` on the PR number when present, falling back to
  github.ref, so pushes to main are never cancelled by PR activity.
- Record why Node is pinned to 20.19.4 next to the pin itself.

main's branch protection currently has required_status_checks empty with
enforcement off, so dropping the separate "lint" context strands nothing.
The job keeps the name "check" to match org-wide protection.

Verified with actionlint (clean).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ashirman
ashirman merged commit cbfd042 into main Jul 30, 2026
1 check passed
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.

3 participants