[GH-ISSUE #7219] [Bug] Bundled IPC paths use the first defineProperty descriptor value instead of the effective value #4304

Closed
opened 2026-10-31 00:48:43 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @SII-YDD on GitHub (Oct 26, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/7219

Before submitting

  • Searched open and closed issues and related PR diffs.
  • Removed credentials and private target data.

Area

JavaScript static analysis / Electron wrapped call paths (CLI and MCP).

Observed behavior

On eecadf35b20ac72d509513bef5949d36c887354d, the compiled CLI and stdio MCP report a candidate IPC path for a bundled export whose final descriptor value is a no-op, and omit it when the final value is the sender. Literal descriptor spreads have the same problem.

Reproduction

Write this self-contained source as preload.cjs in an otherwise empty directory and run rea analyze-javascript-application DIR --format json, or analyze_javascript_application({input_path: DIR, format: "directory"}):

(() => {
  const modules = {
    2(module) { module.exports = require("electron"); },
    5(module, exports, load) {
      const electron = load(2);
      Object.defineProperty(exports, "sender", {
        value: function(channel) { return (...args) => send(channel, ...args); },
        value: function() { return () => {}; }
      });
      function send(channel, ...args) { electron.ipcRenderer.send(channel, ...args); }
    },
    9(module, exports, load) {
      const helper = load(5);
      load(2).contextBridge.exposeInMainWorld("api", {copy: helper.sender("descriptor:copy")});
    }
  };
  function load(id) { const m = {exports:{}}; modules[id].call(m.exports,m,m.exports,load); return m.exports; }
  load(9);
})();

Both public adapters report api.copy -> electron.ipcRenderer.send with channel descriptor:copy. Swapping the two value properties loses that candidate instead. The direct send(channel, ...) syntax is still an observation; the error is the substituted reachable candidate, not that raw observation.

Expected behavior and executed evidence

The effective descriptor value must follow JavaScript object overwrite order. Node 24.22.1 executed six test-owned fixtures with a recording Electron substitute: control, both duplicate orders, both literal-spread orders, and a literal computed "value" key. The no-op finals send nothing; the sender finals send the expected channel. This is independent JavaScript-semantics evidence, not real Electron/provider verification.

Against the unmodified base, two new CLI/MCP regressions fail, along with three symbolic-resolution regressions for a later unknown spread/computed key/getter retaining an earlier export. The same selected suite passes after a local fix (73 tests). Failure logs and full local checks are retained; a focused PR is being prepared.

Source-derived cause and proposed fix

JavaScriptSymbolicBindings indexes Object.defineProperty using descriptor.properties.find(...), selecting the first value. Reuse the existing staticObjectProperty owner to select the effective value, and retain an unresolved write for dynamic descriptors so earlier exports cannot leak through. Related #4724/#4725 concern CommonJS export-name inventory; #6553 concerns a shadowed Object. This report concerns symbolic export values consumed by wrapped call-path analysis.

Impact and scope

Reproduced on synthetic bundled Electron preloads via both compiled public adapters. Incorrect candidates can misdirect an analyst about an exposed API's IPC behavior. Frequency in real applications and formal priority: NOT_ENOUGH_INFO; no P1 claim. No target execution or new provider capability is proposed.

Version / environment

REA 6.8.0 source eecadf35b20ac72d509513bef5949d36c887354d; Linux arm64, Node 24.22.1, npm 11.16.0. No native provider required. AI-assisted investigation and patch preparation.

Originally created by @SII-YDD on GitHub (Oct 26, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7219 ## Before submitting - [x] Searched open and closed issues and related PR diffs. - [x] Removed credentials and private target data. ## Area JavaScript static analysis / Electron wrapped call paths (CLI and MCP). ## Observed behavior On `eecadf35b20ac72d509513bef5949d36c887354d`, the compiled CLI and stdio MCP report a candidate IPC path for a bundled export whose final descriptor value is a no-op, and omit it when the final value is the sender. Literal descriptor spreads have the same problem. ## Reproduction Write this self-contained source as `preload.cjs` in an otherwise empty directory and run `rea analyze-javascript-application DIR --format json`, or `analyze_javascript_application({input_path: DIR, format: "directory"})`: ```js (() => { const modules = { 2(module) { module.exports = require("electron"); }, 5(module, exports, load) { const electron = load(2); Object.defineProperty(exports, "sender", { value: function(channel) { return (...args) => send(channel, ...args); }, value: function() { return () => {}; } }); function send(channel, ...args) { electron.ipcRenderer.send(channel, ...args); } }, 9(module, exports, load) { const helper = load(5); load(2).contextBridge.exposeInMainWorld("api", {copy: helper.sender("descriptor:copy")}); } }; function load(id) { const m = {exports:{}}; modules[id].call(m.exports,m,m.exports,load); return m.exports; } load(9); })(); ``` Both public adapters report `api.copy -> electron.ipcRenderer.send` with channel `descriptor:copy`. Swapping the two `value` properties loses that candidate instead. The direct `send(channel, ...)` syntax is still an observation; the error is the substituted reachable candidate, not that raw observation. ## Expected behavior and executed evidence The effective descriptor value must follow JavaScript object overwrite order. Node 24.22.1 executed six test-owned fixtures with a recording Electron substitute: control, both duplicate orders, both literal-spread orders, and a literal computed `"value"` key. The no-op finals send nothing; the sender finals send the expected channel. This is independent JavaScript-semantics evidence, not real Electron/provider verification. Against the unmodified base, two new CLI/MCP regressions fail, along with three symbolic-resolution regressions for a later unknown spread/computed key/getter retaining an earlier export. The same selected suite passes after a local fix (73 tests). Failure logs and full local checks are retained; a focused PR is being prepared. ## Source-derived cause and proposed fix `JavaScriptSymbolicBindings` indexes `Object.defineProperty` using `descriptor.properties.find(...)`, selecting the first `value`. Reuse the existing `staticObjectProperty` owner to select the effective value, and retain an unresolved write for dynamic descriptors so earlier exports cannot leak through. Related #4724/#4725 concern CommonJS export-name inventory; #6553 concerns a shadowed `Object`. This report concerns symbolic export **values** consumed by wrapped call-path analysis. ## Impact and scope Reproduced on synthetic bundled Electron preloads via both compiled public adapters. Incorrect candidates can misdirect an analyst about an exposed API's IPC behavior. Frequency in real applications and formal priority: NOT_ENOUGH_INFO; no P1 claim. No target execution or new provider capability is proposed. ## Version / environment REA 6.8.0 source `eecadf35b20ac72d509513bef5949d36c887354d`; Linux arm64, Node 24.22.1, npm 11.16.0. No native provider required. AI-assisted investigation and patch preparation.
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#4304
No description provided.