[GH-ISSUE #6435] [Bug] Pathless source-map context loses the selected HTTPS authority for a relative source #3848

Closed
opened 2026-10-31 00:44:36 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @coygeek on GitHub (Oct 23, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/6435

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

The public CLI trace-web-source-location and an initialized production stdio MCP trace_web_source_location call both succeeded but reported the relative source original.ts as https:///original.ts when the selected map URL context was https://app.test. With the same map, script and generated point, https://app.test/ returned https://app.test/original.ts. The map has no sourceRoot. Node reparses the first reported identity with hostname original.ts.

Reproduction

From an already built source checkout with the locked dependencies and pinned Node toolchain, run the following in the checkout root. The manifest uses synthetic historical capture metadata; no capture file or browser is required. The workflow independently reads the three generated manifest/script/map files.

node --input-type=module <<'JS'
import { mkdirSync, writeFileSync } from 'node:fs';
import { createHash } from 'node:crypto';
import { resolve } from 'node:path';
const root = resolve('source-map-url-repro');
const source = 'generated';
mkdirSync(resolve(root, 'files/modules'), { recursive: true });
const manifest = {
  capture_path: resolve(root, 'capture.json'), capture_sha256: 'a'.repeat(64),
  capture_kind: 'browser-scenario', source_evidence_id: null,
  capture_completeness: { status: 'complete', equality_eligible: true, missing_sections: [], truncated_sections: [] },
  output_directory: root, analysis_input: { input_path: root, format: 'directory' }, limitations: [],
  scripts: [{
    url: 'https://app.test/main.js',
    source: { kind: 'scenario-response', transaction_id: 'txn', request_sequence: 1, response_sequence: 2, status: 200 },
    content: {
      state: 'exported', relative_path: 'modules/main.js', layout: 'isolated', layout_reason: 'fixture',
      sha256: createHash('sha256').update(source).digest('hex'), bytes: Buffer.byteLength(source),
      media_type: 'text/javascript', redacted: false, representation: 'browser-decoded-response-bytes'
    }
  }]
};
writeFileSync(resolve(root, 'files/modules/main.js'), source);
writeFileSync(resolve(root, 'manifest.json'), JSON.stringify(manifest));
writeFileSync(resolve(root, 'app.js.map'), JSON.stringify({ version: 3, names: [], sources: ['original.ts'], sourcesContent: ['x'], mappings: 'AAAA' }));
JS
mkdir -p source-map-url-repro/home source-map-url-repro/config source-map-url-repro/cache source-map-url-repro/data source-map-url-repro/temp
for context in 'https://app.test' 'https://app.test/'; do
  env -i PATH="$PATH" HOME="$PWD/source-map-url-repro/home" \
    XDG_CONFIG_HOME="$PWD/source-map-url-repro/config" \
    XDG_CACHE_HOME="$PWD/source-map-url-repro/cache" \
    XDG_DATA_HOME="$PWD/source-map-url-repro/data" \
    TMPDIR="$PWD/source-map-url-repro/temp" REA_LOG_LEVEL=silent \
    node scripts/rea.mjs trace-web-source-location \
    "$PWD/source-map-url-repro/manifest.json" 0 \
    "$PWD/source-map-url-repro/app.js.map" "$context" 1 0 --json
 done

Read normalized_result.url_context and normalized_result.matches[0].resolved_url in each result. The first command succeeds with https:///original.ts; the second succeeds with https://app.test/original.ts. Both exit 0. The inline fixture and complete shell block were replayed successfully in an isolated directory with the built dispatcher available as scripts/rea.mjs.

Expected behavior

For the demonstrated relative source with no sourceRoot, resolve under the selected app.test authority and return the same identity as the equivalent trailing-slash context. Retain the caller's literal url_context. Absolute sources or sourceRoot may select a different authority; this report does not require every source to retain the map context's host. Contract breadcrumbs appear under Relevant output or evidence.

Impact and scope

P2: successful analysis Evidence contains a wrong original-source URL identity for this accepted context. The pathless CLI case reproduced in three fixture replays and once through initialized stdio MCP. A verified workaround is to use https://app.test/. No downstream failure or natural workload frequency was measured. No original source fetch, target execution or security-boundary crossing was observed. CLI additionally reproduced query-only and backslash-separated context variants, but the report's closure is the simple relative-source/pathless-context case.

REA version

Package 6.7.0; tested source checkout 9eb829aca3 with its copied compiled runtime. Release-tag resolution source and dependency pins were inspected; a separately installed release runtime was not executed.

Runtime and platform

Node.js v24.18.0, npm 11.16.0; macOS 27.0.1 arm64; locked @jridgewell/trace-mapping 0.3.31 and @jridgewell/resolve-uri 3.1.2.

Target and artifact context

Synthetic local export_web_scripts-shaped manifest, retained generated script and regular v3 map with embedded original text. No browser, application target or network fetch is needed.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Both CLI commands above exited 0. Relevant successful result fields:

{"url_context":"https://app.test","matches":[{"state":"mapped","reported_source":"original.ts","reported_source_root":null,"resolved_url":"https:///original.ts"}]}
{"url_context":"https://app.test/","matches":[{"state":"mapped","reported_source":"original.ts","reported_source_root":null,"resolved_url":"https://app.test/original.ts"}]}

These are result fragments, not complete Evidence envelopes. The stdio MCP check launched node scripts/rea.mjs mcp, initialized the locked SDK Client over StdioClientTransport, and called trace_web_source_location with the same absolute fixture paths, script_index 0, generated_position {line:1,column:0}, and each of the two contexts. Both responses had isError false and the same respective structured result identities. CLI runtime and initialized MCP runtime were both executed; no service seam substituted for either.

The applicable input/resolution contract is docs/web-source-location.md:16-18,32-34 and src/domain/webSourceLocation.ts:30-35. The URL guard is src/application/WebSourceLocationService.ts:208-217; the literal base enters the codec at src/javascript/sourceMaps/DecodedSourceMap.ts:33-35, and its resolvedSources entry is published at src/javascript/sourceMaps/TraceSourceMap.ts:193-196. Existing adapter/application tests passed: two files, 48 tests, one worker. They do not cover the demonstrated pathless base.

Typed outcome or recovery expected

Successful mapped Evidence with resolved_url: "https://app.test/original.ts" and the literal selected url_context for this fixture. The equivalent slash context must remain successful.

Analysis or suspected cause

Source-derived explanation, confirmed by a direct dependency probe: the pinned codec strips the map filename at the last literal slash before resolving sources, which turns the pathless context into https://. This behavior is inherited from the codec. The locked decoder profile is documented at docs/web-source-location.md:62-69, and src/application/WebSourceLocationService.ts:47-50 explicitly calls resolved URLs codec-derived; neither states that an accepted absolute HTTPS context requires a path or trailing slash. The report does not prescribe changing the dependency or general WHATWG normalization for arbitrary virtual schemes.

Additional context

Restoration check: rerun the exact relative-source fixture and require the pathless result to equal the successful slash control, while preserving each literal url_context. Replacing only sources[0] with https://other.test/original.ts must continue to return that absolute source; this control was executed through the public CLI and succeeded. No last-known-good version or other host platform was established.

Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6435 ## Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ## Area Evidence, artifacts, or reconstruction ## Observed behavior The public CLI `trace-web-source-location` and an initialized production stdio MCP `trace_web_source_location` call both succeeded but reported the relative source `original.ts` as `https:///original.ts` when the selected map URL context was `https://app.test`. With the same map, script and generated point, `https://app.test/` returned `https://app.test/original.ts`. The map has no sourceRoot. Node reparses the first reported identity with hostname `original.ts`. ## Reproduction From an already built source checkout with the locked dependencies and pinned Node toolchain, run the following in the checkout root. The manifest uses synthetic historical capture metadata; no capture file or browser is required. The workflow independently reads the three generated manifest/script/map files. ```sh node --input-type=module <<'JS' import { mkdirSync, writeFileSync } from 'node:fs'; import { createHash } from 'node:crypto'; import { resolve } from 'node:path'; const root = resolve('source-map-url-repro'); const source = 'generated'; mkdirSync(resolve(root, 'files/modules'), { recursive: true }); const manifest = { capture_path: resolve(root, 'capture.json'), capture_sha256: 'a'.repeat(64), capture_kind: 'browser-scenario', source_evidence_id: null, capture_completeness: { status: 'complete', equality_eligible: true, missing_sections: [], truncated_sections: [] }, output_directory: root, analysis_input: { input_path: root, format: 'directory' }, limitations: [], scripts: [{ url: 'https://app.test/main.js', source: { kind: 'scenario-response', transaction_id: 'txn', request_sequence: 1, response_sequence: 2, status: 200 }, content: { state: 'exported', relative_path: 'modules/main.js', layout: 'isolated', layout_reason: 'fixture', sha256: createHash('sha256').update(source).digest('hex'), bytes: Buffer.byteLength(source), media_type: 'text/javascript', redacted: false, representation: 'browser-decoded-response-bytes' } }] }; writeFileSync(resolve(root, 'files/modules/main.js'), source); writeFileSync(resolve(root, 'manifest.json'), JSON.stringify(manifest)); writeFileSync(resolve(root, 'app.js.map'), JSON.stringify({ version: 3, names: [], sources: ['original.ts'], sourcesContent: ['x'], mappings: 'AAAA' })); JS mkdir -p source-map-url-repro/home source-map-url-repro/config source-map-url-repro/cache source-map-url-repro/data source-map-url-repro/temp for context in 'https://app.test' 'https://app.test/'; do env -i PATH="$PATH" HOME="$PWD/source-map-url-repro/home" \ XDG_CONFIG_HOME="$PWD/source-map-url-repro/config" \ XDG_CACHE_HOME="$PWD/source-map-url-repro/cache" \ XDG_DATA_HOME="$PWD/source-map-url-repro/data" \ TMPDIR="$PWD/source-map-url-repro/temp" REA_LOG_LEVEL=silent \ node scripts/rea.mjs trace-web-source-location \ "$PWD/source-map-url-repro/manifest.json" 0 \ "$PWD/source-map-url-repro/app.js.map" "$context" 1 0 --json done ``` Read `normalized_result.url_context` and `normalized_result.matches[0].resolved_url` in each result. The first command succeeds with `https:///original.ts`; the second succeeds with `https://app.test/original.ts`. Both exit 0. The inline fixture and complete shell block were replayed successfully in an isolated directory with the built dispatcher available as scripts/rea.mjs. ## Expected behavior For the demonstrated relative source with no sourceRoot, resolve under the selected app.test authority and return the same identity as the equivalent trailing-slash context. Retain the caller's literal `url_context`. Absolute sources or sourceRoot may select a different authority; this report does not require every source to retain the map context's host. Contract breadcrumbs appear under Relevant output or evidence. ## Impact and scope P2: successful analysis Evidence contains a wrong original-source URL identity for this accepted context. The pathless CLI case reproduced in three fixture replays and once through initialized stdio MCP. A verified workaround is to use `https://app.test/`. No downstream failure or natural workload frequency was measured. No original source fetch, target execution or security-boundary crossing was observed. CLI additionally reproduced query-only and backslash-separated context variants, but the report's closure is the simple relative-source/pathless-context case. ## REA version Package 6.7.0; tested source checkout 9eb829aca34be36ff112826337996f6139f82eff with its copied compiled runtime. Release-tag resolution source and dependency pins were inspected; a separately installed release runtime was not executed. ## Runtime and platform Node.js v24.18.0, npm 11.16.0; macOS 27.0.1 arm64; locked @jridgewell/trace-mapping 0.3.31 and @jridgewell/resolve-uri 3.1.2. ## Target and artifact context Synthetic local export_web_scripts-shaped manifest, retained generated script and regular v3 map with embedded original text. No browser, application target or network fetch is needed. ## Interface CLI ## Earliest failure stage Native analysis or reconstruction ## Relevant output or evidence Both CLI commands above exited 0. Relevant successful result fields: ```json {"url_context":"https://app.test","matches":[{"state":"mapped","reported_source":"original.ts","reported_source_root":null,"resolved_url":"https:///original.ts"}]} {"url_context":"https://app.test/","matches":[{"state":"mapped","reported_source":"original.ts","reported_source_root":null,"resolved_url":"https://app.test/original.ts"}]} ``` These are result fragments, not complete Evidence envelopes. The stdio MCP check launched `node scripts/rea.mjs mcp`, initialized the locked SDK Client over StdioClientTransport, and called `trace_web_source_location` with the same absolute fixture paths, script_index 0, generated_position `{line:1,column:0}`, and each of the two contexts. Both responses had isError false and the same respective structured result identities. CLI runtime and initialized MCP runtime were both executed; no service seam substituted for either. The applicable input/resolution contract is `docs/web-source-location.md:16-18,32-34` and `src/domain/webSourceLocation.ts:30-35`. The URL guard is `src/application/WebSourceLocationService.ts:208-217`; the literal base enters the codec at `src/javascript/sourceMaps/DecodedSourceMap.ts:33-35`, and its resolvedSources entry is published at `src/javascript/sourceMaps/TraceSourceMap.ts:193-196`. Existing adapter/application tests passed: two files, 48 tests, one worker. They do not cover the demonstrated pathless base. ## Typed outcome or recovery expected Successful mapped Evidence with `resolved_url: "https://app.test/original.ts"` and the literal selected url_context for this fixture. The equivalent slash context must remain successful. ## Analysis or suspected cause Source-derived explanation, confirmed by a direct dependency probe: the pinned codec strips the map filename at the last literal slash before resolving sources, which turns the pathless context into `https://`. This behavior is inherited from the codec. The locked decoder profile is documented at `docs/web-source-location.md:62-69`, and `src/application/WebSourceLocationService.ts:47-50` explicitly calls resolved URLs codec-derived; neither states that an accepted absolute HTTPS context requires a path or trailing slash. The report does not prescribe changing the dependency or general WHATWG normalization for arbitrary virtual schemes. ## Additional context Restoration check: rerun the exact relative-source fixture and require the pathless result to equal the successful slash control, while preserving each literal url_context. Replacing only sources[0] with `https://other.test/original.ts` must continue to return that absolute source; this control was executed through the public CLI and succeeded. No last-known-good version or other host platform was established.
Author
Owner

@coygeek commented on GitHub (Oct 24, 2026):

Checked the reported fix on main at d87e73f2db.

Although the pinned TraceMap codec still derives https:///original.ts for the pathless context, the published mapped resolved_url now comes from the shared ECMA-426/WHATWG resolver rather than codec resolvedSources. An isolated production-producer probe with the report map and point returned https://app.test/original.ts for both https://app.test and https://app.test/, preserving each literal url_context; replacing the source with https://other.test/original.ts preserved that absolute authority for both contexts. Existing regressions cover the new shared resolver and mapped identity preservation, but no committed pathless-HTTPS regression was found.

Implementation: javascriptSourceMapPaths.ts, TraceSourceMap.ts.

The relevant regression checks in sourceToBundleComparison.test.ts, TraceSourceMap.test.ts passed in the focused test run on this revision. This closure is based on the current source and those checks; provider fixtures do not establish a real-engine run. Closing as completed on main.

<!-- gh-comment-id:6380713050 --> @coygeek commented on GitHub (Oct 24, 2026): Checked the reported fix on `main` at d87e73f2db50be72d33a4b3c7199af35518b441c. Although the pinned TraceMap codec still derives https:///original.ts for the pathless context, the published mapped resolved_url now comes from the shared ECMA-426/WHATWG resolver rather than codec resolvedSources. An isolated production-producer probe with the report map and point returned https://app.test/original.ts for both https://app.test and https://app.test/, preserving each literal url_context; replacing the source with https://other.test/original.ts preserved that absolute authority for both contexts. Existing regressions cover the new shared resolver and mapped identity preservation, but no committed pathless-HTTPS regression was found. Implementation: [javascriptSourceMapPaths.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/src/domain/javascript/javascriptSourceMapPaths.ts#L48), [TraceSourceMap.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/src/javascript/sourceMaps/TraceSourceMap.ts#L184). The relevant regression checks in [sourceToBundleComparison.test.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/src/domain/javascript/sourceToBundleComparison.test.ts), [TraceSourceMap.test.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/src/javascript/sourceMaps/TraceSourceMap.test.ts) passed in the focused test run on this revision. This closure is based on the current source and those checks; provider fixtures do not establish a real-engine run. Closing as completed on main.
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#3848
No description provided.