[GH-ISSUE #4853] [Bug] Static JavaScript analysis classifies Map.get as an exact network endpoint #3018

Closed
opened 2026-10-31 00:34:54 +00:00 by bsakaguchi · 4 comments
Owner

Originally created by @thomasisalwayslate on GitHub (Oct 17, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/4853

A local JavaScript Map.get() is classified as a network endpoint with state: "observed", confidence: "exact", and no limitations.

Reproduced with the published npm package rea-agents@6.5.0 on macOS ARM64, Node 26.10.0. The npm provenance statement identifies commit 3b79af28e80785afce9f5998d8f03289402a1847. Also reproduced in a source checkout at 63c65a22430a4bbc0c1807a0298edb867775001f.

Create a directory containing only this main.js:

const records = new Map([['/accounts', { name: 'Alice' }]]);
console.log(records.get('/accounts'));

Run:

npx -y rea-agents@6.5.0 analyze-javascript-application /absolute/path/to/repro --json

The returned graph contains an endpoint node with:

{
  "properties": {
    "endpoint_kind": "network",
    "value": "/accounts",
    "mechanism": "call:records.get"
  },
  "evidence": {
    "authority": "ast-static-analysis",
    "state": "observed",
    "confidence": "exact",
    "limitations": []
  }
}

This program performs an in-memory lookup. It has no network API, HTTP client or imported request wrapper. The call site is directly observable in the AST, but its classification as a network endpoint is false.

Expected: recognize this local Map binding and omit the network classification. If receiver semantics cannot be resolved, report an inferred candidate with an explicit limitation rather than exact network semantics.

A control containing fetch('/accounts') produces the expected network classification. These are static-analysis tests; no runtime network observation is claimed.

Originally created by @thomasisalwayslate on GitHub (Oct 17, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4853 A local JavaScript `Map.get()` is classified as a network endpoint with `state: "observed"`, `confidence: "exact"`, and no limitations. Reproduced with the published npm package `rea-agents@6.5.0` on macOS ARM64, Node 26.10.0. The npm provenance statement identifies commit `3b79af28e80785afce9f5998d8f03289402a1847`. Also reproduced in a source checkout at `63c65a22430a4bbc0c1807a0298edb867775001f`. Create a directory containing only this `main.js`: ```js const records = new Map([['/accounts', { name: 'Alice' }]]); console.log(records.get('/accounts')); ``` Run: ```sh npx -y rea-agents@6.5.0 analyze-javascript-application /absolute/path/to/repro --json ``` The returned graph contains an `endpoint` node with: ```json { "properties": { "endpoint_kind": "network", "value": "/accounts", "mechanism": "call:records.get" }, "evidence": { "authority": "ast-static-analysis", "state": "observed", "confidence": "exact", "limitations": [] } } ``` This program performs an in-memory lookup. It has no network API, HTTP client or imported request wrapper. The call site is directly observable in the AST, but its classification as a network endpoint is false. Expected: recognize this local `Map` binding and omit the network classification. If receiver semantics cannot be resolved, report an inferred candidate with an explicit limitation rather than exact network semantics. A control containing `fetch('/accounts')` produces the expected network classification. These are static-analysis tests; no runtime network observation is claimed.
Author
Owner

@Abdooo2235 commented on GitHub (Oct 17, 2026):

@thomasisalwayslate I reproduced this and opened draft #4863. The public CLI now omits the local Map lookup, keeps fetch as exact static API evidence, and qualifies unresolved get/delete receivers as inferred candidates. The fix also checks alias, method and prototype mutations. 187 tests, static checks and docs checks pass locally. If you can rerun the original case, confirmation would be useful. @morluto the PR records the compatibility change and evidence; initial human readiness is pending.

<!-- gh-comment-id:6238662454 --> @Abdooo2235 commented on GitHub (Oct 17, 2026): @thomasisalwayslate I reproduced this and opened draft #4863. The public CLI now omits the local Map lookup, keeps fetch as exact static API evidence, and qualifies unresolved get/delete receivers as inferred candidates. The fix also checks alias, method and prototype mutations. 187 tests, static checks and docs checks pass locally. If you can rerun the original case, confirmation would be useful. @morluto the PR records the compatibility change and evidence; initial human readiness is pending.
Author
Owner

@piyushpcs commented on GitHub (Oct 17, 2026):

Working on this in #4889 (draft PR). Steps are AI-assisted; the diff is human-reviewed and I'll mark Author readiness there once my initial review is complete. The fix adds a keyed-collection receiver fact to the definitions pass, so resolved new Map/Set/Headers/... bindings with a stable immutable initializer stop classifying .get/.delete string arguments as network endpoints; the spelling-only path keeps its current behavior. The exact repro from this issue (along with the fetch control) was verified through analyze-javascript-application --json from the built source checkout: the records.get('/accounts') endpoint node is no longer emitted, and the fetch control still is.

<!-- gh-comment-id:6241409593 --> @piyushpcs commented on GitHub (Oct 17, 2026): Working on this in #4889 (draft PR). Steps are AI-assisted; the diff is human-reviewed and I'll mark Author readiness there once my initial review is complete. The fix adds a `keyed-collection` receiver fact to the definitions pass, so resolved `new Map/Set/Headers/...` bindings with a stable immutable initializer stop classifying `.get`/`.delete` string arguments as network endpoints; the spelling-only path keeps its current behavior. The exact repro from this issue (along with the `fetch` control) was verified through `analyze-javascript-application --json` from the built source checkout: the `records.get('/accounts')` endpoint node is no longer emitted, and the `fetch` control still is.
Author
Owner

@morluto commented on GitHub (Oct 18, 2026):

Fixed on main in fbfdb6abe, with public adapter regressions in 93196449a.

The shared semantic owner now proves unchanged Map get/delete operations before endpoint classification. Application and captured-bundle analysis use the same proof. Unresolved get/delete receivers remain inferred, low-confidence candidates even for URL-shaped arguments; known fetch remains exact static API evidence, not observed traffic.

The producing boundaries retain alias capture, member stores, escaped containers, callable results and direct/indirect eval uncertainty. Native Map operations no longer manufacture whole-receiver escapes: deferred receiver effects settle with real effects to convergence. Iterable construction also checks the set hook, which can install a replacement get/delete. This follows the ECMAScript Map constructor; an authored Node VM control with an inert fetch recorder confirmed the hook behavior without network access.

Adapted the JavaScript changes from @Abdooo2235's #4863, with coauthor credit. Its unrelated Linux resource change was excluded. Additional review fixes cover shared bundle classification, repeated native operations, and the constructor hook. #4889's narrower alias fix leaves unresolved and subsequent-operation certainty gaps.

Executed on macOS 26.3 arm64, Node 24.18.0:

  • Baseline public CLI reproduced exact false Map and unresolved-get endpoints. Source regressions: 107 failed, 7 controls passed before changes.
  • 2,406 JavaScript/bundle source tests passed in 86 files. Four depth/finding-cap stress files were excluded from this bounded run.
  • 172 focused tests passed in six files through rebuilt CLI, worker, graph and public MCP. MCP verifies text/structured Evidence parity, candidate node/edge uncertainty, repeated Map omission and known fetch certainty. The repeated-operation MCP case failed before the producing effect correction; both constructor-hook regressions failed before their correction.
  • check:fast, docs:check (five conformance tests), discovery (1,569 files exactly once), normal pre-commit/pre-push hooks passed. Hooks left tested source content unchanged. Two bounded read-only reviews found no remaining blocker after corrections.

Costs: six completed public CLI tasks against separate baseline e6c487799 and fixed code, same tiny authored input. Warm filesystem median elapsed 1.229→1.235 s, CPU 1.262→1.266 s, 10 ms sampled process-family peak RSS 492.5→496.0 MiB. Source microtasks showed added work (ordinary warm elapsed 11.18→13.34 ms, 150 Map lookups 7.02→9.89 ms). Output intentionally differs for correctness. No speedup claim; OS caches were not flushed. Sampling can miss transient/reparented children. Tokens, large real bundles, large store graphs and MCP process-family costs were not measured; store/root relationships may grow quadratically. Heavy CPU stress and Flameox profiling remain stopped.

These checks establish this issue's bounded static-analysis behavior, not complete runtime behavior, whole-repository validation or completion of the broader audit. Unresolved cases remain candidates. Launcher intent #4847 and XML scalar policy #4852 remain open.

<!-- gh-comment-id:6243707418 --> @morluto commented on GitHub (Oct 18, 2026): Fixed on main in fbfdb6abe, with public adapter regressions in 93196449a. The shared semantic owner now proves unchanged Map get/delete operations before endpoint classification. Application and captured-bundle analysis use the same proof. Unresolved get/delete receivers remain inferred, low-confidence candidates even for URL-shaped arguments; known fetch remains exact static API evidence, not observed traffic. The producing boundaries retain alias capture, member stores, escaped containers, callable results and direct/indirect eval uncertainty. Native Map operations no longer manufacture whole-receiver escapes: deferred receiver effects settle with real effects to convergence. Iterable construction also checks the set hook, which can install a replacement get/delete. This follows the [ECMAScript Map constructor](https://tc39.es/ecma262/multipage/keyed-collections.html#sec-map-iterable); an authored Node VM control with an inert fetch recorder confirmed the hook behavior without network access. Adapted the JavaScript changes from @Abdooo2235's #4863, with coauthor credit. Its unrelated Linux resource change was excluded. Additional review fixes cover shared bundle classification, repeated native operations, and the constructor hook. #4889's narrower alias fix leaves unresolved and subsequent-operation certainty gaps. Executed on macOS 26.3 arm64, Node 24.18.0: - Baseline public CLI reproduced exact false Map and unresolved-get endpoints. Source regressions: 107 failed, 7 controls passed before changes. - 2,406 JavaScript/bundle source tests passed in 86 files. Four depth/finding-cap stress files were excluded from this bounded run. - 172 focused tests passed in six files through rebuilt CLI, worker, graph and public MCP. MCP verifies text/structured Evidence parity, candidate node/edge uncertainty, repeated Map omission and known fetch certainty. The repeated-operation MCP case failed before the producing effect correction; both constructor-hook regressions failed before their correction. - check:fast, docs:check (five conformance tests), discovery (1,569 files exactly once), normal pre-commit/pre-push hooks passed. Hooks left tested source content unchanged. Two bounded read-only reviews found no remaining blocker after corrections. Costs: six completed public CLI tasks against separate baseline e6c487799 and fixed code, same tiny authored input. Warm filesystem median elapsed 1.229→1.235 s, CPU 1.262→1.266 s, 10 ms sampled process-family peak RSS 492.5→496.0 MiB. Source microtasks showed added work (ordinary warm elapsed 11.18→13.34 ms, 150 Map lookups 7.02→9.89 ms). Output intentionally differs for correctness. No speedup claim; OS caches were not flushed. Sampling can miss transient/reparented children. Tokens, large real bundles, large store graphs and MCP process-family costs were not measured; store/root relationships may grow quadratically. Heavy CPU stress and Flameox profiling remain stopped. These checks establish this issue's bounded static-analysis behavior, not complete runtime behavior, whole-repository validation or completion of the broader audit. Unresolved cases remain candidates. Launcher intent #4847 and XML scalar policy #4852 remain open.
Author
Owner

@thomasisalwayslate commented on GitHub (Oct 18, 2026):

Thanks for fixing both of these so quickly! If you credit reporters in the release notes, I'd appreciate a "reported by @thomasisalwayslate" for #4853 and #4854.

<!-- gh-comment-id:6248958543 --> @thomasisalwayslate commented on GitHub (Oct 18, 2026): Thanks for fixing both of these so quickly! If you credit reporters in the release notes, I'd appreciate a "reported by @thomasisalwayslate" for #4853 and #4854.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3018
No description provided.