brace-expansion: nine new DoS advisories outdate the floors set in #103.
Raise the three version-scoped overrides to the patched head of each
major (1.1.21, 2.1.7, 5.0.12). undici: raise the @expo/cli scoped
override to ^6.28.1 (resolves to 6.29.0).
Add smoke checks locking the floors and the minimatch brace/glob
behaviour for every installed minimatch major, so a return to a blanket
override fails the suite.
npm audit: 12 -> 10 entries. The rest is tracked in #123 and #126.
Fixes#124Fixes#125
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Advisories published on 2026-09-08 land above the current floors:
- @xmldom/xmldom <= 0.8.14 (GHSA-c7q8-3ch8-vqpv, GHSA-x4fp-j954-r2f4,
GHSA-93r5-fhx6-vmg9 and 7 more), patched in 0.8.15 (lts line)
- js-yaml < 3.15.2 / < 4.3.2 (GHSA-2883-xcg3-v3hh)
Raise the three overrides. Lock diff is limited to the three entries.
All consumers are build-time tooling (@expo/plist, plist via xcode,
@expo/xcpretty, @istanbuljs/load-nyc-config); the Android bundle hash
is unchanged.
Fixes#121
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@react-navigation/core <= 7.22.0 depends on query-string, which pulls
decode-uri-component <= 0.4.2 (GHSA-vcc3-ghjq-m6fr, DoS on malformed
percent-encoded input). 7.22.1 parses queries itself and drops the
dependency. A scoped override bumps it without touching anything else:
the lock diff is limited to @react-navigation/core and /routers.
Add smoke-test guards for the failure mode of the superseded PR #118
(blanket npm audit fix): babel-preset-expo and @expo/metro-config must
resolve from the root node_modules, only one Expo SDK major may be
installed, every metro copy must stay on 0.83.x. Replayed against the
PR #118 lock, all four checks fail. Also add a deep link round trip
through getStateFromPath/getPathFromState with query params.
Fixes#117
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Version was still recorded as 1.6.4/16 while master is at 1.6.6/18.
Records the security remediation outcome (19 vulns / 9 HIGH -> 10 / 0
HIGH), the override inventory, and the three @expo/metro shims that no
longer resolve under metro 0.83.8 -- inert today, but worth re-checking
at the next Expo SDK bump.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Y4GzEsmDryrwtQcmBNw9P
browserslist <= 4.28.6 carries two HIGH advisories published 2026-09-01:
GHSA-c83g-rgw3-j3cx (unbounded memory growth, no cache eviction, leading
to OOM) and GHSA-73wf-gq98-2v4g (uncaught crash / prototype write via an
untrusted browserslist-stats.json in normalizeStats). Both report
first_patched_version = 4.28.7.
Unlike the image-size root fixed in #114, this one has a published fix,
so a plain version floor is enough. Every requester already uses a caret
range compatible with 4.28.7 (@babel/helper-compilation-targets ^4.24.0,
@expo/metro-config ^4.25.0, core-js-compat ^4.28.1, update-browserslist-db
peer >= 4.21.0) -- the lock was simply pinned at 4.28.1. The override
records the security floor the same way as the existing esbuild,
@xmldom/xmldom, postcss, brace-expansion and @babel/core entries.
Resolves to 4.28.9. npm audit: 11 -> 10 total, 1 HIGH -> 0 HIGH. No high
or critical finding remains in the tree.
Verified: the lock stays unchanged under re-resolution against
package.json, npm ci accepts the pair (what EAS runs), npm test 11/11,
and expo export --platform android emits a byte-identical Hermes bundle
(index-3d9ab1a7942c6dfccc79d9b280b8ce80.hbc, 8.17 MB) -- the compilation
targets browserslist resolves are unchanged.
Refs #115
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Y4GzEsmDryrwtQcmBNw9P
metro@0.83.8 (published 2026-08-19) removed the image-size dependency and
vendored a reduced dimension parser (src/lib/imageSize.js) that supports
only bmp/gif/jpeg/ktx/png/psd/svg/tiff/webp. The ICNS, JXL and HEIF
parsers named by GHSA-w3rx-r6r6-pgpr and GHSA-5p2g-fcmc-qvqq are absent
from it, so the DoS is eliminated by construction rather than by an
upstream patch: image-size still publishes no fixed version (latest is
2.0.2, and both advisories report first_patched_version = None).
metro@0.83.3 was the only requester of image-size in the whole tree, so
every transitive HIGH finding collapses with it.
@expo/metro@54.2.0 pins the 14 metro packages to exact 0.83.3, so npm
update cannot move them and an override is required. All 14 are moved
together to avoid a mixed metro tree; the existing nested ws override is
preserved through the "." key.
npm audit: 19 -> 11 total, 9 HIGH -> 1 HIGH. The remaining HIGH
(browserslist) is unrelated and pre-existing on master.
Verified: image-size absent from both the lock file and node_modules,
14 metro packages resolved to 0.83.8 with no duplicates, patch-package
postinstall still applies, npm test 11/11, and expo export --platform
android produces a Hermes bundle with PNG dimension variations resolved
through the vendored parser.
Refs #108
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Y4GzEsmDryrwtQcmBNw9P
- brace-expansion -> ^1.1.18 / ^2.1.4 / ^5.0.9 (version-scoped per major):
DoS advisories (exponential-time expansion + unbounded OOM). Version-scoping
bumps each major within its own major, preserving the CJS export contract
(default export for 1.x/2.x, named for 5.x) that a blanket override would have
broken. This is #103's original blocker, now resolved. Verified: minimatch@3
glob resolution works (the exact call that TypeError'd under a blanket).
- @babel/core -> ^7.29.6 (resolves 7.29.7): GHSA-4x5r-pxfx-6jf8 arbitrary file
read via sourceMappingURL (vulnerable <=7.29.0, ~87 deduped instances).
Both build/dev-time only, not bundled in the shipped APK. npm audit 14 -> 12;
the remaining 12 high are entirely the image-size upstream-locked cascade
(no published fix, tracked in #108). Smoke test 11/11, lock diff is 1:1 version
replacements (large count driven by @babel/core's deduped instances).
Fixes#103Fixes#110
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- @expo/cli > undici ^6.27.0 -> ^6.28.0: GHSA-8xcm-r25x-g524 / m8rv-5g2x-5cg5
/ v3r7-h72x-cjcm (response desync, CRLF & cookie injection; vulnerable <6.28.0)
- js-yaml -> ^3.15.1 (3.x) + ^4.3.1 (4.x): CVE-2026-59870 / GHSA-5p4m-2wfm-xmqj
(quadratic CPU in !!omap resolution; vulnerable 3.x<3.15.1, 4.x<4.3.1)
js-yaml moved from parent-scoped overrides (@expo/xcpretty,
@istanbuljs/load-nyc-config) to version-scoped ones (js-yaml@^3 / js-yaml@^4):
the 4.x instance is reached via @expo/cli, which is itself overridden, and a
nested override does not propagate through an overridden parent (npm left
js-yaml@4.3.0 "invalid"). Version-scoped targeting resolves it regardless of
the parent path.
Both build/dev-time only, not bundled in the shipped APK. npm audit drops
undici + js-yaml (16 -> 14). Remaining 13 high = image-size + its metro/RN
cascade (upstream-locked, tracked in #108) + @babel/core low. Smoke test green,
widget patch reapplied, lock diff limited to the 3 bumped packages.
Fixes#106Fixes#107
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- postcss ^8.5.10 -> ^8.5.18 (resolves to 8.5.26): GHSA-r28c-9q8g-f849,
path traversal in source-map auto-loading (vulnerable <=8.5.17)
- @expo/cli > tar ^7.5.19 -> ^7.5.21 (resolves to 7.5.22): GHSA-r292-9mhp-454m,
uncontrolled recursion stack-overflow DoS (vulnerable <=7.5.20)
- nanoid 3.3.11 -> 3.3.18 pulled in by postcss re-resolution (bonus)
Both are build/dev-time only, not bundled in the shipped APK. npm audit no
longer lists postcss (nor its transitive inflation expo/@expo/cli/
@expo/metro-config) nor tar. Smoke test green (11/11), widget patch-package
reapplied, diff limited to package.json + package-lock.json.
Fixes#102Fixes#104
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Upgrade react-native-android-widget 0.20.1 -> 0.21.0 (expedited
WorkManager upstream, clickable-area ripple corner fix)
- patch-package on the lib:
1. WIDGET_CLICK bypasses WorkManager and runs the headless JS task
directly on the ReactHost (goAsync + WorkManager fallback), removing
two Room writes + worker dispatch from every tap and WorkManager
init from the cold path
2. WEBP_LOSSLESS (effort 0) encoding instead of PNG q100 on API 30+,
several times faster for widget-sized bitmaps
3. Copy identical light/dark collection item files instead of
compressing every row bitmap twice when the config is single-mode
- Extract dependency-light src/services/widgetState.ts so the headless
click handler no longer pulls DB/drizzle/date-fns at cold start
- Smoke tests: lock the light import graph + patch/postinstall wiring
- Bump v1.6.5 (versionCode 17) for the preview build
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds scoped overrides for shell-quote (GHSA-w7jw-789q-3m8p, critical),
undici (4 CVEs, high), ws (GHSA-96hv-2xvq-fx4p, high — distinct from the
CVE already fixed in #92/#94), js-yaml (GHSA-h67p-54hq-rp68, moderate,
two incompatible majors need separate scopes), and tar
(GHSA-vmf3-w455-68vh, moderate). All 5 are dev-tooling-only (Expo CLI,
Metro, react-devtools-core) with no runtime app code path.
Verified: npm audit clean on all 5 packages, smoke test passes, Metro
Bundler boots and serves /status normally after the ws bump (the only
scope touching Fast Refresh/dev-middleware runtime).
Fixes#95, Fixes#96, Fixes#97, Fixes#98, Fixes#99
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
npm audit flagged ws 8.0.0-8.20.0 (moderate, uninitialized memory
disclosure) pulled in via expo > @expo/cli > ws@8.20.0. Scope the
override to @expo/cli so only the vulnerable 8.x instance is bumped
(resolved to 8.21.0); metro's ws@7.5.10 and react-native's ws@6.2.3
stay on their majors to avoid breaking the Metro dev server.
All ws here is dev/build tooling (Expo CLI, Metro, react-devtools),
absent from the shipped APK, so this was not exploitable in production
- but the override clears npm audit and stops the Defenseur re-flagging.
npm audit: 0 vulnerabilities. Root smoke green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ThemeToggle's mount effect reads localStorage then setTheme, a pattern
react-hooks/set-state-in-effect flags. It is safe here: localStorage is
SSR-unavailable so the read must happen post-mount, and ThemeScript
already applies the dark class before hydration (no page FOUC). Add a
targeted eslint-disable-next-line with justification.
web/ lint is now green (0 errors).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Three pre-existing lint issues surfaced during #70's lint check:
- lists/[id]/page.tsx: subtasksMap was `let`, never reassigned -> const
- api/lists/[id]/tasks/route.ts: query was `let`, never reassigned -> const
- Header.tsx: drop unused `Link` import from next/link
Leaves web/ lint at a single remaining error (ThemeToggle
set-state-in-effect), tracked in #90 (needs a design decision:
useSyncExternalStore vs documented eslint-disable).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
getAuthenticatedUser only read ID token claims, where `name` is often
absent, so the web app showed the user's email instead of their name
after SSO. Fetch the userInfo endpoint and resolve the display name with
the same fallback order as the vitrine (la-compagnie-maximus#80):
userInfo.name -> userInfo.username -> claims.name -> claims.username,
with the email fallback applied in the layout. Email now also prefers
userInfo over claims.
Single source of truth in auth.ts (only producer of `name`, consumed
solely by layout.tsx -> Header). layout.tsx and Header.tsx verified,
left unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The previous override ^11.0.0 allowed the vulnerable range 11.0.0 - 11.1.0.
npm resolved on 11.1.0, leaving the buffer-bounds-check CVE active in
v3/v5/v6 with buf arg. Bumping to ^11.1.1 stays in the 11.x major (CJS
compat preserved per past revert at 800f777) and fixes the advisory.
npm audit: 0 vulnerabilities. smoke tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Plain-node script invoked via `npm test`. Catches the buffer-bounds
regression area from GHSA-w5hq-g745-h8pq (uuid v3/v5 with buffer arg)
and validates package.json structure. No jest/Expo runtime needed —
runs in seconds, suitable for the defenseur-auto chain to gate auto-PRs.
Captures lesson from v1.6.2 release: when curl reports HTTP 502/504 ~60s
into the upload of a 90+ MB APK, the cause is client-side bandwidth dropping
under ~1.5 MB/s, not Traefik or Forgejo config. Retry — bandwidth recovers.
Adds: retry loop, diagnostics checklist, correct DELETE asset path
(/releases/{release_id}/assets/{asset_id}, not /releases/assets/{asset_id}).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>