diff --git a/GITHUB_ISSUES.md b/GITHUB_ISSUES.md index 8b31e99..1d22414 100644 --- a/GITHUB_ISSUES.md +++ b/GITHUB_ISSUES.md @@ -189,12 +189,12 @@ Repository changes can implement tests/workflow shape, but OIDC/IAM/environment ## SUPPLY-001 — Remove vulnerable dependency chains and stage SDK/build upgrades **Labels:** `priority:P0`, `type:maintenance`, `type:security`, `area:web`, `area:firebase`, `area:stripe`, `size:L` -**Status:** Partial; SUPPLY-001A is represented by [#127](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/127), SUPPLY-001B by [#192](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/192), and SUPPLY-001C source/tests by [#202](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/202); D–G remain open +**Status:** Partial; SUPPLY-001A is represented by [#127](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/127), SUPPLY-001B by [#192](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/192), SUPPLY-001C source/tests by [#202](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/202), and focused SUPPLY-001D8 by [#453](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/453); the main D–G upgrades remain open **Depends on:** CI-001A ### Problem -The 2026-07-12 baseline production audit reported 33 root advisories (3 critical, 9 high) and 9 Functions advisories (1 high). SUPPLY-001A/#127 removes the unused `gpxparser` and obsolete `jsdom/request/form-data` chain; on a fresh Node 20 install, the root production audit falls to 22 advisories (1 critical, 8 high) while production bundle hashes remain identical. SUPPLY-001B/#192 pins the compatible React Router 6.30.4 graph and removes all three router findings, reducing that root audit to 19 advisories (1 critical, 5 high). SUPPLY-001C/#202 pins the last Firebase 11 compatibility release and its matching Rules helper; its fresh production audit reports 6 advisories (0 critical, 3 high). Firebase Admin still needs a staged major upgrade, Create React App remains unmaintained, and scanning/policy automation remains open. +The 2026-07-12 baseline production audit reported 33 root advisories (3 critical, 9 high) and 9 Functions advisories (1 high). SUPPLY-001A/#127 removes the unused `gpxparser` and obsolete `jsdom/request/form-data` chain; on a fresh Node 20 install, the root production audit falls to 22 advisories (1 critical, 8 high) while production bundle hashes remain identical. SUPPLY-001B/#192 pins the compatible React Router 6.30.4 graph and removes all three router findings, reducing that root audit to 19 advisories (1 critical, 5 high). SUPPLY-001C/#202 pins the last Firebase 11 compatibility release and its matching Rules helper; its fresh production audit reports 6 advisories (0 critical, 3 high). Later focused lock repairs reduce the exact-main snapshot to 4 findings (3 high, 1 low) before SUPPLY-001D8/#453; D8 removes the high-severity SystemJS compiler finding through an already-compatible parent range. Firebase Admin and the Firebase CLI still need staged major upgrades, Create React App remains unmaintained, and scanning/policy automation remains open. ### Scope @@ -225,10 +225,11 @@ Deliver as small ordered PRs: - SUPPLY-001A/#127: source search finds no runtime use; a fresh Node 20 lockfile install contains no `gpxparser`; 50 entries are removed with no retained package identity change; the root production audit changes from 33 to 22; all 47 frontend and 10 standalone SPA tests pass; and optimized JS/CSS asset hashes match the baseline exactly. - SUPPLY-001B/#192: the root declaration and only the three router package records change; a fresh Node 20 production audit changes from 22 findings (1 critical, 8 high, 12 moderate, 1 low) to 19 (1 critical, 5 high, 12 moderate, 1 low), with no remaining router entry. A fail-before/pass-after test covers the compatibility warnings; the focused suite also covers double-slash normalization, wildcard-to-home navigation, login return-path handling, account routing, and the 10-test standalone callback boundary. - SUPPLY-001C/#202: exact Firebase 11.10.0 and Rules helper 4.0.1 resolve the root production `protobufjs` path to 7.6.5 and remove Firebase's root `undici` path. The fresh production audit changes from 19 findings (1 critical, 5 high, 12 moderate, 1 low) to 6 (0 critical, 3 high, 2 moderate, 1 low). A red test proves the upgraded Rules helper cannot discover the emulator in the old Jest sandbox; the Node 20 native-web-API environment makes all 348 Rules cases pass. Focused Firebase/Auth/App Check tests pass 71/71, the frontend passes 198/198, Functions pass 1,077/1,077 applicable unit tests, and the callback and release-safety suites pass. Reproducible clean builds change the optimized main bundle from `main.fdd058b4.js` to `main.56edbdb7.js`: +8.29 kB gzip (about 3.3%) and +180 KiB on disk overall (about 1.0%). A dev-only older `protobufjs` remains nested under `firebase-tools`; the remaining six root and nine Functions production findings are still open. +- SUPPLY-001D8/#453: keep `package.json` and `@babel/preset-env` 7.26.9 byte-compatible while moving the sole `@babel/plugin-transform-modules-systemjs` resolution from affected 7.25.9 to reviewed 7.29.7 through the existing `^7.25.9` range. The exact lock closure is 16 entries. A dependency-free RED test pins the identity/topology and reproduces upstream's safe string-export case: the old plugin emits malformed identifier syntax, while the patched plugin emits a computed string key. A fresh Node 20 production audit changes from 4 findings (3 high, 1 low) to 3 (2 high, 1 low) with no GHSA-fv7c-fp4j-7gwp. All 49 non-source-map build files are byte-identical; only the main source map changes, retaining the same 477 sources and contents while its updated mapping/name tables add 2,574 bytes. ### Agent handoff -Never use `npm audit fix --force`. Do not combine all upgrades in one unreviewable lockfile diff. SUPPLY-001A, B, and C are represented by #127, #192, and #202; do not publish duplicates. #202 is source/test evidence only: it does not publish the website, deploy Firebase, change provider settings, or prove live behavior. Stop if a later provider SDK change needs a product/runtime decision. +Never use `npm audit fix --force`. Do not combine all upgrades in one unreviewable lockfile diff. SUPPLY-001A, B, C, and focused D8 are represented by #127, #192, #202, and #453; do not publish duplicates. #202 and #453 are source/test evidence only: they do not publish the website, deploy Firebase, change provider settings, or prove live behavior. The remaining Babel-core, brace-expansion, minimatch, Firebase CLI, and Functions findings are unresolved and not accepted as safe. Stop if a later provider SDK change needs a product/runtime decision. --- diff --git a/GITHUB_ISSUE_SLICES.md b/GITHUB_ISSUE_SLICES.md index f7144da..38a0ad1 100644 --- a/GITHUB_ISSUE_SLICES.md +++ b/GITHUB_ISSUE_SLICES.md @@ -25,6 +25,7 @@ An agent-ready child has one observable outcome, one trust boundary, explicit de | SUPPLY-001A | published as [#127](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/127); CI-001A | Prove `gpxparser` unused and remove its obsolete transitive chain. | `rg`/tree proof, before/after audits, root lockfile diff, full frontend checks. | | SUPPLY-001B | source/test delivery tracked in [#192](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/192); CI-001A | Pin React Router DOM/Router 6.30.4 and `@remix-run/router` 1.23.3; opt the declarative routers into `v7_startTransition` and `v7_relativeSplatPath` without a route redesign. | Exact three-node lock diff; Node 20 production audit 22→19 and high 8→5 with no router finding; focused route/future-flag tests, standalone callback suite, full CI, and build. | | SUPPLY-001C | source/tests tracked in live [#202](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/202); CI-001A | Pin the Firebase browser SDK to 11.10.0 and its Rules test helper to 4.0.1; bridge Node 20's native web APIs into the isolated Jest Rules environment without changing application behavior or provider settings. | Root production audit 19→6, critical 1→0, and high 5→3; focused Firebase/Auth/App Check tests, full frontend/Functions/Rules suites, standalone callback and safety suites, diagnostic build, dependency tree, and bundle comparison. Website publication, Firebase deployment, provider configuration, and live behavior remain unproven. | +| SUPPLY-001D8 | source/tests tracked in [#453](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/453); CI-001A | Resolve the sole root SystemJS compiler transform from affected 7.25.9 to reviewed 7.29.7 through the unchanged `@babel/preset-env` 7.26.9 `^7.25.9` range, with no manifest or application change. | RED identity and upstream string-export regression; exact 16-entry lock closure; Node 20 production audit 4→3 and high 3→2 with GHSA-fv7c-fp4j-7gwp absent; all 49 non-map build files byte-identical and only the main source map's mapping/name tables changed. No website, Firebase, provider, or live claim. | | SUPPLY-001D | proposed; CI-001A | Upgrade Firebase Admin/Functions in one supported set. | Node 20 lint/unit/emulator/trigger tests and deploy compatibility notes. | | SUPPLY-001E | proposed; PAY-003C | Upgrade Stripe SDK and deliberately select/test an API version. | Signed fixture/test-mode diff and rollback notes; no live endpoint change. | | SUPPLY-001F | proposed; CI-001B2, A–C | Replace CRA while preserving env handling, SPA callbacks, sitemap/SEO, code splitting, and deploy output. | Full CI, bundle/SEO comparison, staging dry run. | diff --git a/OPERATIONS_RUNBOOK.md b/OPERATIONS_RUNBOOK.md index d1bb421..5abbeee 100644 --- a/OPERATIONS_RUNBOOK.md +++ b/OPERATIONS_RUNBOOK.md @@ -330,6 +330,10 @@ The upgraded Rules helper fails before rule evaluation if Jest does not receive This is source and synthetic test evidence only. It does not publish the website, deploy Firebase, change an outside provider, or prove production behavior. Use the protected release process and record each affected surface separately before making any live claim. +SUPPLY-001D8 [#453](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/453) is the focused source/test record for GHSA-fv7c-fp4j-7gwp. It keeps `package.json` and `@babel/preset-env` 7.26.9 unchanged while the existing `^7.25.9` range resolves the sole SystemJS transform from affected 7.25.9 to reviewed 7.29.7. The lock changes exactly 16 records. The dependency test pins the public-registry identity and uses upstream's safe string-export case to prove computed property output. A clean Node 20 production audit changes from 4 findings (3 high, 1 low) to 3 (2 high, 1 low), with the SystemJS advisory absent. The remaining Babel-core, brace-expansion, and minimatch results are still open and are not accepted as safe. + +Clean before/after builds keep the same 49 non-map files, 9,975,968 bytes, and aggregate SHA-256 `3fa30c6d66827277432dcf7d42b0ead9e9fd543c9907571b092cfa43ba3f1e46`. Only the main source map changes. Its 477 source paths and contents are identical; updated mapping/name tables add 2,574 bytes. This does not change public runtime code. It does not publish the website, deploy Firebase, configure a provider, inspect production data, or prove live behavior. + ### Race checkout request boundary — SOURCE ONLY, NOT LIVE PAY-001B1 [#219](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/219) makes the race checkout Function reject malformed or unexpected signup data in two steps. First, it checks one exact, bounded request shape before opening Firestore. Second, after the read-only commerce admission returns the event snapshot, it checks every submitted answer against the event's bounded participant or volunteer field definitions. A denial uses one fixed message and must occur before a rate-limit write, role or capacity call, token creation, registration write, Stripe Product creation, or Stripe Checkout Session call. diff --git a/SECURITY.md b/SECURITY.md index 22abaf8..c112039 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -128,6 +128,7 @@ These entries are implementation evidence, not a production risk-acceptance deci | Part of RISK-014 | SUPPLY-001D5 [#355](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/355) resolves the sole root development-only `shell-quote` node from 1.8.3 to the patched 1.8.4 release without changing `package.json`; both transitive development-tool parents (`launch-editor` `^1.8.1`, `react-dev-utils` `^1.7.3`) already admit it. The exact lock change touches only that node's version, public-registry URL, and integrity while its development flag, license, funding, and `>= 0.4` engine stay fixed. A dependency-free Node test pins the exact installed and locked identity, one hoisted resolution, absent direct manifest/override declaration, and unchanged parent ranges; synthetic public-API regressions prove that object operators containing line feed, carriage return, or either Unicode line separator now throw before a shell can receive them, while an admitted operator and ordinary safe quoting remain available. A fresh 2026-07-18 UTC Node 20.20.2/npm 11.8.0 full audit falls from 66 findings (2 critical) to 65 (1 critical), while the production-only snapshot remains 6 findings (0 critical, 3 high, 2 moderate, 1 low). | No application source imports `shell-quote`, and clean before/after optimized builds on the same toolchain are byte-identical: the same 59 files and 19,435,972 bytes. The sorted per-file SHA-256 manifest has aggregate SHA-256 `b68017a13d8cc88ee9132606b87db60c97852c091e2bd8f12375d6e3f9099a0b`. The remaining root critical `protobufjs` finding is in the old development-only `firebase-tools` chain and requires a separate reviewed major upgrade; all other root and Functions findings also remain unresolved and are not accepted as safe. This source/test change does not publish the website, deploy Firebase, change a provider, inspect production data, or prove live behavior. | | Part of RISK-014 | SUPPLY-001D6 [#381](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/381) resolves the sole root `picomatch` 2.x node from 2.3.1 to the patched 2.3.2 release without changing `package.json`; the existing `jest-util` `^2.2.3` and `micromatch` `^2.3.1` ranges already admit it. The exact lock change touches only that node's version, public-registry URL, and integrity while its non-development classification, MIT license, `>=8.6` engine, parent ranges, and the separate development-only `tinyglobby` picomatch 4.0.4 copy stay fixed. A dependency-free Node test pins those identities and ranges; deterministic public-API regressions prove that inherited POSIX names cannot inject host method text into a compiled expression while ordinary `[[:alpha:]]` matching remains compatible. A fresh 2026-07-19 UTC Node 20.19.5/npm 10.8.2 full audit falls from 65 findings (1 critical, 32 high) to 64 (1 critical, 31 high), and the production-only snapshot falls from 6 findings (0 critical, 3 high, 2 moderate, 1 low) to 5 (0 critical, 2 high, 2 moderate, 1 low), removing GHSA-3v7f-55p6-f55p and GHSA-c2c7-rcm5-vvqj from the sole affected node. | No application source imports `picomatch`, and clean before/after optimized builds on the same toolchain are byte-identical: the same 59 files and 19,475,953 bytes. The sorted per-file SHA-256 manifest has aggregate SHA-256 `57f2db4d6217de2f4e158d357aa928cb0af2b6a18238d61d3d866ffd53f234ba`. `npm ls picomatch --all` still reports the pre-existing hoisted `fdir` `^3 || ^4` mismatch; this patch neither introduces nor repairs that separate build-tool layout debt. The remaining root critical `protobufjs` finding is in the old development-only `firebase-tools` chain and requires a separate major CLI, emulator, and protected-release compatibility review; all other root and Functions findings also remain unresolved and are not accepted as safe. This source/test change does not publish the website, deploy Firebase, change a provider, inspect production data, or prove live behavior. | | Part of RISK-014 | SUPPLY-001D7 [#385](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/385) resolves the sole root, non-development `yaml` 1.x node from 1.10.2 to the patched 1.10.3 release without changing `package.json`; the existing `cosmiconfig` `^1.10.0`, `cssnano` `^1.10.2`, and nested `cosmiconfig` `^1.7.2` ranges already admit it. The exact lock change touches only that node's version, public-registry URL, and integrity while the three separate development-only `yaml` 2.x copies remain fixed. A dependency-free Node test pins all four locked identities and development classifications, the three unchanged parent ranges, and the installed root version. Its fixed 601-byte collection input runs in a bounded child process with a reduced stack and proves the patched public `parseDocument` API reports one parser-owned `YAMLSemanticError` instead of exposing raw `RangeError` failures. A fresh 2026-07-19 UTC Node 20.20.2/npm 10.8.2 full audit remains 64 findings (1 critical, 31 high, 19 moderate, 13 low) because vulnerable development-only `yaml` 2.7.1 and 2.8.0 copies remain; the production-only snapshot falls from 5 findings (2 high, 2 moderate, 1 low) to 4 (2 high, 1 moderate, 1 low). | No application source imports `yaml`, and clean before/after optimized builds on the same toolchain are byte-identical: the same 59 files and 19,489,263 bytes. The sorted per-file SHA-256 manifest has aggregate SHA-256 `0207e35601232cd74febaa6e72b9e2322f2159276f32d9ce046f8b050f0f40ed`. The two affected development-only `yaml` 2.x copies and all other root and Functions findings remain unresolved and are not accepted as safe; they require separate compatibility review rather than widening this lock-only production patch. Source, tests, and any merge do not publish the website, deploy Firebase, change a provider, inspect production data, or prove live behavior. | +| Part of RISK-014 | SUPPLY-001D8 [#453](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/453) removes GHSA-fv7c-fp4j-7gwp / CVE-2026-44728 from the root production build graph. The sole `@babel/plugin-transform-modules-systemjs` node moves from affected 7.25.9 to reviewed 7.29.7 through `@babel/preset-env` 7.26.9's unchanged `^7.25.9` range; `package.json` is byte-identical and no direct dependency or override is added. The exact lock closure updates 13 Babel records, updates two `@jridgewell` mapping records, and removes one now-unused mapping helper. A dependency-free test pins the sole installed/locked public-registry identity and closure. Its safe upstream-derived string-export fixture fails before the patch because Babel emits malformed identifier syntax and passes afterward with a computed string property. A fresh 2026-07-22 UTC Node 20.19.5/npm 10.8.2 full audit changes from 65 findings (2 critical, 33 high, 17 moderate, 13 low) to 64 (2 critical, 32 high, 17 moderate, 13 low); the production-only snapshot changes from 4 findings (3 high, 1 low) to 3 (2 high, 1 low), with no SystemJS advisory. | MPRC does not offer a user-input compiler endpoint, but compiling trusted source only is not a reason to retain a high-severity build-chain defect. Clean exact-lock builds keep all 49 non-map files byte-identical at 9,975,968 bytes with aggregate SHA-256 `3fa30c6d66827277432dcf7d42b0ead9e9fd543c9907571b092cfa43ba3f1e46`. Only `main.85f5094a.js.map` changes: its 477 source paths and contents remain byte-identical, while updated name/mapping tables add 2,574 bytes. The separate Babel-core low and brace-expansion/minimatch high findings, old development-only Firebase CLI critical paths, and all Functions findings remain unresolved and are not accepted as safe. Source, tests, and any merge do not publish the website, deploy Firebase, change a provider, inspect production data, or prove live behavior. | | Part of RISK-024 | SEC-001 protects token documents from every browser client. | OAUTH-001 must still add transactional refresh/versioning, scope/account binding, disconnect/revocation, IAM/encryption decision, and redacted lifecycle audit. | | RISK-009, part of RISK-024 | OAUTH-001C1H [#441](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/441) replaces browser-generated/session-storage-authoritative Strava OAuth state with a 32-byte server-issued challenge. Source stores only a SHA-256 digest in one browser-denied per-UID secret record, binds it to exact UID and decoded Auth `auth_time`, expires it after ten minutes, and transactionally deletes one match before provider exchange or connection writes. A later begin overwrites the older record; mismatch, expiry, replay, and the concurrent loser stop with one fixed result before Strava. Synthetic tests use mocks and no real callback or provider value. | This source does not deploy either Function or the website, configure Strava, prove the custom App Check guard is enabled, enable native runtime App Check enforcement, inspect production data, or prove live OAuth behavior. #443 separately supplies only the source/test clean-page readiness handoff while preserving initial callback suppression. Scope/account policy, refresh concurrency, provider/local reconciliation, revoke/audit, IAM/encryption, configured Enterprise evidence, native enforcement, and provider/live evidence remain open under [#88](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/88). | | RISK-008, RISK-009, part of RISK-024 | OAUTH-001C1I [#443](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/443) preserves initial capability-callback App Check suppression, then permits only a document that began on a normalized Strava callback to initialize the existing Enterprise provider after both current callback locations are clean, Router page state is `null`, and native history state is absent or the exact matching BrowserRouter index/key/empty-user-state record. One single-flight readiness attempt precedes one existing exchange. Before exchange admission, the callback rechecks the clean path, Router entry key, and exact UID, service, Firebase resources, app, attempt, and page lifecycle; dirty or reinjected paths, extra or mismatched history state, missing configuration, provider/readiness failure, or stale mounted context use one fixed failure and make no exchange, while an unmounted completion is inert. Authentication, registration, and shop callbacks are ineligible and keep their existing flow. The method never receives callback values or returns, inspects, logs, or stores the token-ready result. Local/test remain off and ordinary production startup remains eager. | This is source and synthetic-test ordering evidence only. It does not configure an Enterprise key or domains, prove a provider-backed token or Firebase acceptance, enable native `enforceAppCheck`, change a Function or Rule, publish the website, deploy Firebase, configure or contact Strava, inspect production data, or prove live OAuth behavior. App Check initialization is not reversible; later reinjection is scrubbed/discarded but earlier browser, hosting, provider, and network copies are not erased. A lifecycle or reinjection change after exchange admission cannot cancel server or provider work already started; it blocks another exchange and obsolete UI, but reconciliation may still be required. Complete ABUSE-001A2 only after protected provider and exact-revision staging evidence. Account/scope policy, refresh concurrency, reconciliation, revoke/audit, IAM/encryption, deployment, and live proof keep [#88](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/88) open. | diff --git a/package-lock.json b/package-lock.json index 1ddf18a..b069ad0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -95,14 +95,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -175,15 +175,15 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { @@ -272,6 +272,15 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", @@ -286,27 +295,27 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -328,9 +337,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -384,18 +393,18 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -438,12 +447,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.27.0" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -1342,15 +1351,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", - "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz", + "integrity": "sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==", "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -2030,45 +2039,45 @@ } }, "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -4705,17 +4714,13 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -4727,15 +4732,6 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/source-map": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", @@ -4754,9 +4750,9 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", diff --git a/tests/root-dependency-security.test.js b/tests/root-dependency-security.test.js index 5f0c81b..e106a65 100644 --- a/tests/root-dependency-security.test.js +++ b/tests/root-dependency-security.test.js @@ -53,6 +53,28 @@ const EXPECTED_NESTED_PICOMATCH = Object.freeze({ resolved: 'https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz', integrity: 'sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==', }); +const EXPECTED_SYSTEMJS_TRANSFORM = Object.freeze({ + version: '7.29.7', + resolved: 'https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz', + integrity: 'sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==', +}); +const EXPECTED_SYSTEMJS_LOCK_CLOSURE = Object.freeze({ + 'node_modules/@babel/code-frame': '7.29.7', + 'node_modules/@babel/generator': '7.29.7', + 'node_modules/@babel/helper-globals': '7.29.7', + 'node_modules/@babel/helper-module-imports': '7.29.7', + 'node_modules/@babel/helper-module-transforms': '7.29.7', + 'node_modules/@babel/helper-plugin-utils': '7.29.7', + 'node_modules/@babel/helper-string-parser': '7.29.7', + 'node_modules/@babel/helper-validator-identifier': '7.29.7', + 'node_modules/@babel/parser': '7.29.7', + 'node_modules/@babel/plugin-transform-modules-systemjs': '7.29.7', + 'node_modules/@babel/template': '7.29.7', + 'node_modules/@babel/traverse': '7.29.7', + 'node_modules/@babel/types': '7.29.7', + 'node_modules/@jridgewell/gen-mapping': '0.3.13', + 'node_modules/@jridgewell/trace-mapping': '0.3.31', +}); const EXPECTED_YAML = Object.freeze({ version: '1.10.3', resolved: 'https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz', @@ -453,6 +475,81 @@ test('does not compile inherited POSIX class names into host method text', () => assert.equal(alpha.test('7'), false); }); +test('pins the sole SystemJS transform resolution to the reviewed patched chain', () => { + const packageJson = readJson(PACKAGE_PATH); + const lock = readJson(LOCK_PATH); + + assert.equal(packageJson.dependencies?.['@babel/plugin-transform-modules-systemjs'], undefined); + assert.equal(packageJson.devDependencies?.['@babel/plugin-transform-modules-systemjs'], undefined); + assert.equal(packageJson.optionalDependencies?.['@babel/plugin-transform-modules-systemjs'], undefined); + assert.equal(packageJson.peerDependencies?.['@babel/plugin-transform-modules-systemjs'], undefined); + assert.equal(packageJson.resolutions?.['@babel/plugin-transform-modules-systemjs'], undefined); + assert.equal(packageJson.overrides?.['@babel/plugin-transform-modules-systemjs'], undefined); + + const preset = lock.packages['node_modules/@babel/preset-env']; + assert.equal(preset?.version, '7.26.9'); + assert.equal( + preset?.dependencies?.['@babel/plugin-transform-modules-systemjs'], + '^7.25.9', + ); + + const lockedPaths = Object.keys(lock.packages).filter((packagePath) => ( + packagePath === 'node_modules/@babel/plugin-transform-modules-systemjs' + || packagePath.endsWith('/node_modules/@babel/plugin-transform-modules-systemjs') + )); + assert.deepEqual(lockedPaths, ['node_modules/@babel/plugin-transform-modules-systemjs']); + + const transform = lock.packages['node_modules/@babel/plugin-transform-modules-systemjs']; + assert.deepEqual( + { + version: transform?.version, + resolved: transform?.resolved, + integrity: transform?.integrity, + }, + EXPECTED_SYSTEMJS_TRANSFORM, + 'the SystemJS transform must retain its reviewed public-registry identity', + ); + assert.notEqual(transform?.dev, true); + + for (const [packagePath, version] of Object.entries(EXPECTED_SYSTEMJS_LOCK_CLOSURE)) { + const record = lock.packages[packagePath]; + assert.equal(record?.version, version, `${packagePath} must retain its reviewed version`); + assert.match(record?.resolved ?? '', /^https:\/\/registry\.npmjs\.org\//); + assert.match(record?.integrity ?? '', /^sha512-/); + assert.notEqual(record?.dev, true); + } + assert.equal(lock.packages['node_modules/@jridgewell/set-array'], undefined); + + const installed = readJson(path.join( + REPOSITORY, + 'node_modules/@babel/plugin-transform-modules-systemjs/package.json', + )); + assert.equal(installed.version, EXPECTED_SYSTEMJS_TRANSFORM.version); +}); + +test('emits computed syntax for an upstream SystemJS string-export fixture', () => { + const babel = require(path.join(REPOSITORY, 'node_modules/@babel/core')); + const systemJsTransform = require(path.join( + REPOSITORY, + 'node_modules/@babel/plugin-transform-modules-systemjs', + )); + const source = [ + 'var foo, bar;', + 'export {foo as "default exports", bar} from "./other.mjs";', + 'export * from "./other.mjs";', + ].join('\n'); + + const output = babel.transformSync(source, { + babelrc: false, + configFile: false, + plugins: [systemJsTransform], + }).code; + + assert.match(output, /_exportObj\["default exports"\] = _otherMjs\.foo;/); + assert.doesNotMatch(output, /_exportObj\.default exports/); + assert.doesNotThrow(() => new Function(output)); // eslint-disable-line no-new-func +}); + test('pins the sole root yaml 1.x resolution to the patched 1.10.3 release', () => { const packageJson = readJson(PACKAGE_PATH); const lock = readJson(LOCK_PATH);