[GH-ISSUE #4500] [Bug] Electron inspection retains a script from an excluded srcdoc frame under a synthetic local-file sourceURL #1783

Closed
opened 2026-10-16 21:10:14 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @wmmalcolm on GitHub (Oct 16, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/4500

Area

Process capture or runtime observation.

Observed behavior

CdpElectronProvider.inspectPage() excludes an about:srcdoc frame as out_of_target_scope, but retains that frame’s script when its sourceURL names an existing local file.

The retained record:

  • Uses the named file’s canonical path as file_path.
  • Has frame_id: null, although Chromium supplied the script’s execution-context frame ID.
  • Includes script bytes that differ from the named file.
  • Omits Chromium’s hasSourceURL: true indicator.

This was reproduced against real Chromium through REA’s unchanged production provider. It was not a mocked CDP response or a CLI/MCP reproduction.

Reproduction

Reduced sequence from the executed Playwright/provider harness:

  1. Create two synthetic local files:

    innocent.js:

    globalThis.__reaInnocent = true;
    

    index.html:

    <!doctype html>
    <script src="innocent.js"></script>
    
  2. Launch an isolated headless Chromium profile with --remote-debugging-port=0, then open index.html.

  3. Append a srcdoc frame containing a harmless script with a source label pointing to the existing innocent.js:

    const source = [
      'globalThis.__reaSyntheticMarker = "REA_SYNTHETIC_SRCDOC_CONTEXT";',
      `//# sourceURL=${pathToFileURL(innocentPath).href}`,
    ].join('\n');
    
    await page.evaluate(source => {
      const frame = document.createElement('iframe');
      frame.srcdoc = '<script>' + source + '</script>';
      document.body.append(frame);
    }, source);
    
  4. Independently observe Debugger.scriptParsed. Chromium reports the supplied file URL, hasSourceURL: true, and the srcdoc frame’s ID in executionContextAuxData.

  5. Use CdpElectronProvider.listTargets() to select the local index.html target, then call:

    const result = await provider.inspectPage({
      cdp_endpoint: endpoint,
      target_id: target.target_id,
      observation_ms: 0,
      include_script_sources: true,
    });
    
  6. Find the retained script whose source contains REA_SYNTHETIC_SRCDOC_CONTEXT. Compare its file_path, frame_id, and source digest with the named disk file.

Relevant results

The provider returned ok: true.

The result excluded the srcdoc frame:

{
  "section": "frames",
  "reason": "out_of_target_scope",
  "count": 1
}

Nevertheless, the marker script remained in scripts.items, with:

file_path = canonical path of innocent.js
frame_id = null
source.included = true
source.artifact.sha256 != SHA-256 of innocent.js

The disk file remained unchanged. The result’s overall completeness was policy_filtered, not fully complete. The owned browser and provider connections were closed afterward.

Expected behavior

A supplied script label should remain distinguishable from verified filesystem provenance.

If the script’s known execution context belongs to an excluded frame, either exclude that script consistently or retain an explicit attribution/scope warning. Do not silently replace the known excluded-frame relationship with null while presenting the label as a canonical local-file path.

Impact and limits

The demonstrated impact is misleading source attribution and inconsistent frame filtering in an otherwise successful capture. A consumer could associate runtime code with the wrong local file.

This does not demonstrate arbitrary file reading, exfiltration, code execution in REA, or application compromise. Script-source capture was explicitly enabled. The named file was a synthetic fixture owned by the test.

The successful reproduction uses about:srcdoc. A remote HTTP-frame exploit was not established. Downstream reconciliation effects, packaged Electron applications, other platforms, and published-package applicability remain unverified.

Version and environment

  • Source revision: 180ba03bfddd5916251e81e97a500b1ede7a9eea
  • Node.js: 26.5.0
  • Chromium: 155.0.8059.80
  • Platform: macOS
  • Interface: direct production-provider invocation
  • Earliest failure stage: capture/result projection

Source-derived explanation

Script admission checks the reported URL against an existing local file, but retains scripts whose frame is outside frameIds, assigning null.

Event ingestion does not preserve hasSourceURL.

No exact matching report was found in targeted issue/PR searches during validation. #3382 concerns attribution after context destruction; #917 concerns separate browser execution/listener tools.

This report comes from AI-assisted review with local runtime reproduction. No fix or post-fix verification is claimed.

Originally created by @wmmalcolm on GitHub (Oct 16, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4500 ## Area Process capture or runtime observation. ## Observed behavior `CdpElectronProvider.inspectPage()` excludes an `about:srcdoc` frame as `out_of_target_scope`, but retains that frame’s script when its `sourceURL` names an existing local file. The retained record: - Uses the named file’s canonical path as `file_path`. - Has `frame_id: null`, although Chromium supplied the script’s execution-context frame ID. - Includes script bytes that differ from the named file. - Omits Chromium’s `hasSourceURL: true` indicator. This was reproduced against real Chromium through REA’s unchanged production provider. It was not a mocked CDP response or a CLI/MCP reproduction. ## Reproduction Reduced sequence from the executed Playwright/provider harness: 1. Create two synthetic local files: `innocent.js`: ```js globalThis.__reaInnocent = true; ``` `index.html`: ```html <!doctype html> <script src="innocent.js"></script> ``` 2. Launch an isolated headless Chromium profile with `--remote-debugging-port=0`, then open `index.html`. 3. Append a `srcdoc` frame containing a harmless script with a source label pointing to the existing `innocent.js`: ```js const source = [ 'globalThis.__reaSyntheticMarker = "REA_SYNTHETIC_SRCDOC_CONTEXT";', `//# sourceURL=${pathToFileURL(innocentPath).href}`, ].join('\n'); await page.evaluate(source => { const frame = document.createElement('iframe'); frame.srcdoc = '<script>' + source + '</script>'; document.body.append(frame); }, source); ``` 4. Independently observe `Debugger.scriptParsed`. Chromium reports the supplied file URL, `hasSourceURL: true`, and the srcdoc frame’s ID in `executionContextAuxData`. 5. Use `CdpElectronProvider.listTargets()` to select the local `index.html` target, then call: ```js const result = await provider.inspectPage({ cdp_endpoint: endpoint, target_id: target.target_id, observation_ms: 0, include_script_sources: true, }); ``` 6. Find the retained script whose source contains `REA_SYNTHETIC_SRCDOC_CONTEXT`. Compare its `file_path`, `frame_id`, and source digest with the named disk file. ## Relevant results The provider returned `ok: true`. The result excluded the srcdoc frame: ```json { "section": "frames", "reason": "out_of_target_scope", "count": 1 } ``` Nevertheless, the marker script remained in `scripts.items`, with: ```text file_path = canonical path of innocent.js frame_id = null source.included = true source.artifact.sha256 != SHA-256 of innocent.js ``` The disk file remained unchanged. The result’s overall completeness was `policy_filtered`, not fully complete. The owned browser and provider connections were closed afterward. ## Expected behavior A supplied script label should remain distinguishable from verified filesystem provenance. If the script’s known execution context belongs to an excluded frame, either exclude that script consistently or retain an explicit attribution/scope warning. Do not silently replace the known excluded-frame relationship with `null` while presenting the label as a canonical local-file path. ## Impact and limits The demonstrated impact is misleading source attribution and inconsistent frame filtering in an otherwise successful capture. A consumer could associate runtime code with the wrong local file. This does **not** demonstrate arbitrary file reading, exfiltration, code execution in REA, or application compromise. Script-source capture was explicitly enabled. The named file was a synthetic fixture owned by the test. The successful reproduction uses `about:srcdoc`. A remote HTTP-frame exploit was not established. Downstream reconciliation effects, packaged Electron applications, other platforms, and published-package applicability remain unverified. ## Version and environment - Source revision: `180ba03bfddd5916251e81e97a500b1ede7a9eea` - Node.js: `26.5.0` - Chromium: `155.0.8059.80` - Platform: macOS - Interface: direct production-provider invocation - Earliest failure stage: capture/result projection ## Source-derived explanation [Script admission](https://github.com/morluto/rea/blob/180ba03bfddd5916251e81e97a500b1ede7a9eea/src/browser/CdpElectronScripts.ts#L31) checks the reported URL against an existing local file, but retains scripts whose frame is outside `frameIds`, assigning `null`. [Event ingestion](https://github.com/morluto/rea/blob/180ba03bfddd5916251e81e97a500b1ede7a9eea/src/browser/CdpElectronScriptEvents.ts#L41) does not preserve `hasSourceURL`. ## Related work No exact matching report was found in targeted issue/PR searches during validation. #3382 concerns attribution after context destruction; #917 concerns separate browser execution/listener tools. This report comes from AI-assisted review with local runtime reproduction. No fix or post-fix verification is claimed.
Author
Owner

@Siva-2517 commented on GitHub (Oct 16, 2026):

Hi, I'd like to work on this issue. I'll investigate the script admission and CDP event ingestion paths, add a regression test for the excluded about:srcdoc frame scenario, and implement a minimal fix that preserves correct frame attribution and sourceURL metadata. I'll first verify the existing behavior against the current upstream code to avoid duplicating any recent changes.

<!-- gh-comment-id:6218604202 --> @Siva-2517 commented on GitHub (Oct 16, 2026): Hi, I'd like to work on this issue. I'll investigate the script admission and CDP event ingestion paths, add a regression test for the excluded `about:srcdoc` frame scenario, and implement a minimal fix that preserves correct frame attribution and `sourceURL` metadata. I'll first verify the existing behavior against the current upstream code to avoid duplicating any recent changes.
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#1783
No description provided.