Skip to content

Fix denial of service from malicious indexed source maps (CVE-2026-93749) - #79

Merged
7rulnik merged 1 commit into
mainfrom
fix/cve-2026-93749
Sep 30, 2026
Merged

7rulnik merged 1 commit into
mainfrom
fix/cve-2026-93749

Conversation

@7rulnik

@7rulnik 7rulnik commented Sep 30, 2026

Copy link
Copy Markdown
Owner

Summary

A crafted source map could exhaust CPU or memory. This fixes four amplification paths reachable from untrusted map input (CVE-2026-93749).

  • Huge section offset.line copied into a generator. An indexed section with an enormous offset.line, once its mappings were copied into a SourceMapGenerator, expanded into one ; per generated line. Section offsets are now validated as non-negative safe integers, and offset.line is capped at 10,000,000, counting summed offsets of nested sections.
  • Exponential sources getter. IndexedSourceMapConsumer's sources getter re-read each nested consumer's sources once per item, which is exponential in nesting depth. It now reads each section's sources a single time.
  • Rope blowup in _serializeMappings. Large ; runs were built one node at a time, forming a rope that could exhaust the heap. Large gaps are now built with a single flat string.
  • Per-line padding in fromStringWithSourceMap. Padding past the end of the generated code added one empty line at a time. It now stops once the code is exhausted, which also fixes literal undefined text being emitted for those lines.

Testing

  • npm test passes (145/145), including six new regression tests covering each path above.
  • Reproduced each path against the pre-patch code under a capped heap and a kill deadline: the original OOMs or times out, the patched code either rejects the input immediately or completes in bounded time and memory.
Path Malicious input Before After
offset into generator offset.line 1e8 OOM at 512MB throws instantly
nested sources getter nesting depth 40 killed at 45s ~1ms at depth 500
serialize line gap gap 1e8 OOM at 512MB flat string, ok
source-node offset offset.line 1e8 OOM at 512MB throws instantly

The exponential path, measured on the pre-patch getter (ms by nesting depth), roughly triples per level:

depth  10   11   12   13   14   15    16    17
ms      3    5   11   28   79  213   608  1700

)

A crafted source map could exhaust CPU or memory through four paths:

* An indexed section with a huge offset.line, once its mappings were
  copied into a SourceMapGenerator, expanded into one ';' per generated
  line. Section offsets are now validated as non-negative safe integers
  and offset.line is capped (including summed nested-section offsets).
* IndexedSourceMapConsumer's sources getter re-read each nested
  consumer's sources per item, which is exponential in nesting depth.
  It now reads each section's sources once.
* _serializeMappings built large ';' runs one node at a time, creating a
  rope that could exhaust the heap. Large gaps are now built with a
  single flat string.
* fromStringWithSourceMap padded past the end of the generated code one
  empty line at a time. It now stops once the code is exhausted, which
  also fixes literal "undefined" text being emitted for those lines.
@7rulnik
7rulnik merged commit cf76580 into main Sep 30, 2026
@7rulnik
7rulnik deleted the fix/cve-2026-93749 branch September 30, 2026 13:18
hateem2121 added a commit to hateem2121/RUN-APPAREL-W.D that referenced this pull request Oct 6, 2026
…#135)

Three high advisories published 2026-10-05 23:28-23:30 UTC, after the day's
last green audit run. All three had patched releases on npm past the 24h
minimumReleaseAge cooldown, so all three are overrides in pnpm-workspace.yaml
(proxy-addr ^2.0.8, compression ^1.8.2, source-map-js ^1.2.2) — zero new
allowlist entries; the allowlist keeps its getting-back-to-empty trajectory.

- GHSA-jqcg-44mw-7w3h proxy-addr IP spoofing via IPv4-mapped IPv6 trust subnet
- GHSA-vc2v-76pw-4v95 compression DoS via memory leak on premature close
- GHSA-68fv-2mgg-jv7q source-map-js event-loop DoS via crafted indexed maps
  (upstream fix 7rulnik/source-map-js#79, v1.2.2 published 2026-09-30)

Measured 2026-10-06: audit-ci exits 0; 5,812 tests pass across the workspace
(the one cms failure is the machine-local .agents/skills/.claude folder, not
these changes). Dated fix note + DELETE conditions in audit-ci.jsonc.
seathatflowsinourveins added a commit to seathatflowsinourveins/native-agent-stack that referenced this pull request Oct 6, 2026
)

### Scope

Fix the newly reviewed advisories that blocked every required OSV check: target only fsspec 2026.6.0/multidict 6.9.1 in the OpenHands runtime lock, Mako 1.4.2 in the application Python lock, and source-map-js 1.2.2 in its pnpm lock. Preserve all other package pins and the original captured artifact bytes.

The command center selected a dated source-backed exception for the frozen macOS input in its isolated config, and exclusion of both retired Lumibot lockchecks after the owner's confirmation. Each lock has native before/after evidence and its supported installation/qualification checks. No workflow or branch-protection setting changes.

- Base: `ecfa112764c664d35377dd66b8cfcb67e5a94d60` (fetch confirmed current main).
- Lane: `lane:foundation`.
- Owned scope: three production locks, SDK pins/research/evidence, qualification and ruling receipts, bounded OSV configuration/inventory, existing binding/no-use guards and closure record. Evidence registry committed last.

## SOTA sources

- [fsspec advisory GHSA-27vj-qcqg-25rc](GHSA-27vj-qcqg-25rc), [official 2026.6.0 release metadata](https://pypi.org/pypi/fsspec/2026.6.0/json), [maintainer tag](https://github.com/fsspec/filesystem_spec/tree/2026.6.0).
- [multidict advisory GHSA-54p9-h82j-f925](GHSA-54p9-h82j-f925), [official 6.9.1 release](https://github.com/aio-libs/multidict/releases/tag/v6.9.1), [PyPI metadata](https://pypi.org/pypi/multidict/6.9.1/json).
- [Mako advisory GHSA-5639-2j2p-m4mx](GHSA-5639-2j2p-m4mx), [maintainer release](https://github.com/sqlalchemy/mako/releases/tag/rel_1_4_2), [official metadata](https://pypi.org/pypi/Mako/1.4.2/json).
- [source-map-js advisory GHSA-68fv-2mgg-jv7q](GHSA-68fv-2mgg-jv7q), [published 1.2.2 metadata](https://registry.npmjs.org/source-map-js/1.2.2), [maintainer fix PR79](7rulnik/source-map-js#79).
- Dependent ranges: [Hugging Face Hub0.35.3](https://pypi.org/pypi/huggingface-hub/0.35.3/json), [aiohttp3.14.3](https://pypi.org/pypi/aiohttp/3.14.3/json), [yarl1.22.0](https://pypi.org/pypi/yarl/1.22.0/json), [Alembic1.20.0](https://pypi.org/pypi/alembic/1.20.0/json), [PostCSS8.5.23](https://registry.npmjs.org/postcss/8.5.23). Complete declared-parent checks include optional/null metadata handling; limitations remain explicit in receipts.
- [#562 at74cc5468](#562): original builder/relock/hash/install/scan/guard pattern. Installed [uv0.12.22](https://github.com/astral-sh/uv/releases/tag/0.12.22) reproduces the accepted baseline byte for byte; #562's0.12.17 remains historical.
- [#587 at798ac445](#587), [#252 atc96c2555](#252): bounded frontend qualification. [pnpm12.4.2 update parser](https://github.com/pnpm/pnpm/blob/9502f3c457717dae3a4ddbf4315a8c4aee16fdb4/pnpm/crates/cli/src/cli_args/update.rs) and [supported update docs](https://pnpm.io/cli/update): selective bare-name transitive update, no-save/lockfile-only; obsolete explicit-version/Infinity forms avoided.
- Frozen config precedent [8fc8611](8fc8611) and the maintained closure at `docs/decisions/2026-09-22-github-automation-closure.md`. Indexed source offsets/reconstruction inspected at [source-map-js1.2.1](https://github.com/7rulnik/source-map-js/blob/428d49f6b1e1614f082b7706fa879a3d9c64f728/lib/source-map-consumer.js#L944). Dedicated input/digest/expiry guards retained.
- Trial [#336 at20b52a5b](#336), existing captured XNYS exclusion precedent, and command-center ruling `task-ns2604-coop-20261006T003954Z`. The verified owner confirmation is a **report** row: `report-native-agent-stack-5f-20261006T0045Z-osv`, from `native-agent-stack-5f`, at `2026-10-06T00:41:23Z`, replying to `task-native-agent-stack-5f-20261006T004011Z`. Sanitized evidence: `evidence/receipts/osv-captured-lumibot-lockchecks-20261005.json`. No trial replay or new host-process census is claimed.

### Evidence-class table

| Claim | Class | Actual result |
| --- | --- | --- |
| Published dependent ranges permit the fixes | source_review | Complete pinned metadata review; no caps/errors; exact parents linked above |
| Targeted locks preserve other pins | local_integration | SDK byte-identical control; only two package blocks move. Mako only package block, native lock revision3→5 recorded. pnpm manager/importers unchanged; only source-map-js move |
| Release identity and supported artifact hashes match | local_integration | Native hash checks0: fsspec2, multidict14, Mako2; universal wheels/sdist included |
| Supported isolated/native qualification succeeds | local_integration | SDK178-package check/imports0; backend28-package check/import/render0; frontend frozen install/peers/typecheck/build0 |
| Both required scan partitions pass locally | local_integration | Before:60ordinary/1frozen,5+1 unignored findings. After:58ordinary/1frozen, actual native exits0/0, zero unignored findings |
| Binding/coverage/no-use guards remain effective | local_integration / synthetic |70 touched tests0; clean control0; all deliberate negative controls1 as expected |
| Registry integrity | local_integration | validate.py0;69components/4profiles/212receipts/10309hashes; integrity only |
| Hosted, image, provider and full API/browser acceptance | unknown | No claim; command-center exact-head cross-family read remains pending |

### Local commands run

All heavy phases used nice19; scratch/cache and installs were isolated. Exact supported commands and sanitized actual returned output/hashes are retained in the three relock prefixes and linked receipts.

```
#562-pattern paired native uv control/targeted lock/check/export:0
native release hash checks:0
hashed SDK install / uv pip check / exact imports:0
targeted Mako lock/check; frozen/no-build sync; pip check; imports/render:0
pnpm12.4.2 update source-map-js --no-save --lockfile-only --ignore-scripts:0
pnpm install --frozen-lockfile --ignore-scripts; peers check; typecheck; build:0
python -m unittest tests.test_openhands_lock_binding tests.test_osv_lockfile_coverage tests.test_frozen_macos_variant_no_use
70 tests; latest final data-pin run6.936s; exit0
OSV2.6.0 ordinary scan:0; frozen scan:0
python3 scripts/validate.py:0,10309hashes
component_matrix --write:0,32rows/zero flips
new_host_grand_list --write:0,32layers/66winners
git diff --check and git diff --cached --check:0
```

### Failed conditions

The initial root-added UV_NO_CONFIG1 discarded the resolver's Linux workspace settings; the next copied formatter inserted two plus signs. Native lock/check/export succeeded in both, while the relock byte-comparison script failed. Neither candidate was adopted; both are disclosed separately. Test preflight rejected inside-checkout TMPDIR before execution; existing external lane cache was used. Intermediate stale receipt/unreviewed metadata-line guards failed before being corrected. Publication caught one private interpreter path in a negative-control trace; it was sanitized. Terminal progress whitespace was normalized and its capture hash rebound. No failure is promoted to a passing upstream test.

### Decision record

`docs/decisions/2026-09-22-github-automation-closure.md`, "Four production relocks and preserved receipt inputs (2026-10-06)"; SDK research section and qualification/ruling receipts record alternatives, source/replay limits and overturn conditions. The macOS exception expires2026-12-24; its `.frozen` rename is a separate follow-up. Future use of captured trial dependencies requires a separately maintained/scanned qualification environment.

### Host evidence

No evidence/hosts or platform-status flip. The native runtime imports/builds are local integration; source reviews, synthetic controls and hosted acceptance remain separate. Exact-head command-center review is requested.

### Checklist

- [x] No workflow/action permission or branch-protection change.
- [x] No credential value or authentication store read/printed/copied; no new required secret.
- [x] No paid hosting, provider/model runtime call, deployment or restart.
- [x] Peer-owned worktrees preserved; three captured locks remain byte-identical.
- [x] Registry committed last; one lane:foundation label.
- [x] Ordinary AND frozen native scans and touched tests passed before ready.
- [ ] Command-center exact-head cross-family read and 5f landing; lane never merges.

## Dated input-binding repair (2026-10-06)

The command-center exact-head read of67c6594d2 found two omitted downstream gates: both convergence records still resolved their original UV digest through the newly relocked live file, and the recipe ledger's PNPM current digest was stale. This amendment preserves trial evidence instead of attributing new dependencies to the original runs.

- Retain ecfa112 UV/PNPM bytes and the two pre-amendment experiment snapshots byte-for-byte.
- Change only each canonical record's UV input path; keep frozen digests, commands, observations, outputs and usage. Both records remain declared.
- Append dated recipe supersession/current mappings and ordered path relocations; protect original/prior/superseded bytes and all non-path record bytes with the portability assertions.
- Source: [#252 path-only relocation](https://github.com/seathatflowsinourveins/native-agent-stack/blob/c96c2555c2d84683d9e519623354c814aeb6a584/blueprints/convergence-practice/application-delivery/history/recipe-revisions.json#L121) and [#587 supersession](https://github.com/seathatflowsinourveins/native-agent-stack/blob/798ac445307e2cd8eba6e74d7722ac0e16da02c7/blueprints/convergence-practice/application-delivery/history/recipe-revisions.json#L99).
- Dated decision/source receipt: `docs/decisions/2026-10-06-application-input-binding-amendment.md`, `evidence/receipts/pr765-bindings-amendment-20261006.json`.

Before repair, all-recorded convergence exited1 (2invalid/32) and native-maintenance exited1 (29cases/one PNPM mismatch). Repaired focused checks: native-maintenance29passed; convergence/OSVcoverage/frozenMAC102passed. After main-registry refresh and full own-file re-registration, local validate0/10315hashes and all-recorded convergence0/32valid. Full local suite ran under A22's specific copied-fixture `install.sh --list` exception and exited1:10,343tests/2217.568s,18failures/18errors/905skips. Installer apply paths remain banned. Raw output is retained privately; known systemd parser (#767), missing calendar/mutation imports, PATH fixtures, token-canary fixtures and installed Windows Terminal type drift are recorded separately, never presented as a pass.

Old reviewed head's hosted baseline was6/7 required contexts: validate failed, six others passed. Required acceptance is measured at the new pushed head; no workflow rerun loop or old local check is promoted into that acceptance. No production pin, recorded trial output, raw receipt, frozen macOS lock, captured trading lock or scanner exclusion changed in this repair.
meta-codesync Bot pushed a commit to facebook/memlab that referenced this pull request Oct 9, 2026
Summary:
Bumps [[https://github.com/7rulnik/source-map-js | source-map-js]] from 1.2.1 to 1.2.2.

== Release notes ==

//Sourced from [[https://github.com/7rulnik/source-map-js/releases | source-map-js's releases]].//

> **v1.2.2**
>
> - Fix crash when executing in browser with CSP script-src that don't permit unsafe-eval ([[7rulnik/source-map-js#29 | #29]]) [[https://github.com/xfournet | @​xfournet]]
> - Fix denial of service from malicious indexed source maps (CVE-2026-93749) ([[7rulnik/source-map-js#79 | #79]]) Reported by [[https://github.com/waydeshi | @​waydeshi]] in [[7rulnik/source-map-js#76 | #76]]. A fix was also proposed by [[https://github.com/aniebiet | @​aniebiet]] in [[7rulnik/source-map-js#78 | #78]].

== Changelog ==

//Sourced from [[https://github.com/7rulnik/source-map-js/blob/main/CHANGELOG.md | source-map-js's changelog]].//

> **1.2.2**
>
> - Fix crash when executing in browser with CSP script-src that don't permit unsafe-eval ([[7rulnik/source-map-js#29 | #29]]) [[https://github.com/xfournet | @​xfournet]]
> - Fix denial of service from malicious indexed source maps (CVE-2026-93749) ([[7rulnik/source-map-js#79 | #79]]) Reported by [[https://github.com/waydeshi | @​waydeshi]] in [[7rulnik/source-map-js#76 | #76]]. A fix was also proposed by [[https://github.com/aniebiet | @​aniebiet]] in [[7rulnik/source-map-js#78 | #78]].

== Commits ==

- [[7rulnik/source-map-js@0a1d334 | 0a1d334]] 1.2.2
- [[7rulnik/source-map-js@4c6fa26 | 4c6fa26]] Update changelog
- [[7rulnik/source-map-js@cf76580 | cf76580]] Fix denial of service from malicious indexed source maps (CVE-2026-93749) ([[7rulnik/source-map-js#79 | #79]])
- [[7rulnik/source-map-js@7899a86 | 7899a86]] Fix crash when executing browser with CSP script-src that don't permit unsafe...
- See full diff in [[7rulnik/source-map-js@v1.2.1...v1.2.2 | compare view]]

Pull Request resolved: #161

Reviewed By: boujeepossum

Differential Revision: D124273775

Pulled By: JacksonGL

fbshipit-source-id: db3ef2c2a265f6211e8bbcf6cda1ca4c3b890c6e
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