[GH-ISSUE #1782] [Bug] Percent-encoded local source-map URLs fail to resolve inventoried files #600

Closed
opened 2026-10-15 18:26:31 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @N0zoM1z0 on GitHub (Oct 11, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/1782

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

analyze-javascript-application retains a percent-encoded source-map URL correctly but fails to resolve it to the existing local source-map filename. For //# sourceMappingURL=app%20part.js.map, the graph inventories app part.js.map yet records its reference as resolved_path: null, available: false.

The public CLI also fails for %25 (literal percent), %2520 (a filename containing the literal text %20, requiring exactly one decode), and an encoded-space URL with query/fragment suffixes. Ordinary unencoded sibling paths resolve successfully.

Reproduction

  1. Build revision 914ba833ded5f8604345de4e4f6d306de0a38c4e using the pinned toolchain: npm ci and npm run build:cached.
  2. Generate this small local fixture with Node:
import { mkdtempSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
const root = mkdtempSync(join(tmpdir(), 'rea-map-encoding-'));
writeFileSync(join(root, 'app.js'),
  'export const value=1;\n//# sourceMappingURL=app%20part.js.map\n');
writeFileSync(join(root, 'app part.js.map'),
  JSON.stringify({version: 3, file: 'app.js', sources: [], names: [], mappings: ''}));
console.log(root);
  1. Run node scripts/rea.mjs analyze-javascript-application /tmp/PRINTED-DIRECTORY --max-heap-mb 512 --json.
  2. Inspect normalized_result.graph: the reference is unavailable even though the exact decoded local map is inventoried.

Expected behavior

Use URL path semantics for local source-map lookup: decode the path once, normalize/confine it at the owning boundary, and resolve the selected local file. Preserve the original declared_url, its digest, and its source location. Query and fragment text should not become filesystem filename components.

Impact and scope

Source-map linkage is lost for valid URL-encoded local filenames, including ordinary spaces. Verified through the public CLI with tiny local fixtures; all runs exit 0 with complete graph coverage. This is independent of directive-token extraction: the full encoded declaration is already present in the failing output. Other consumers of the shared url-reference resolver have not been runtime-tested in this report.

REA version

6.4.0 source build, commit 914ba833ded5f8604345de4e4f6d306de0a38c4e.

Runtime and platform

Linux x64; Node.js 24.18.0; npm 11.16.0. CLI probes ran serially on one CPU, with 512 MiB Node/analysis-worker heaps. Native Windows/macOS execution was not tested; no native provider is needed.

Target and artifact context

Source-owned JavaScript module and valid empty v3 source-map file in a temporary directory. No external URL fetching, target execution, or sensitive artifacts involved.

Interface

CLI

Earliest failure stage

Artifact or evidence registration

Relevant output or evidence

For the %20 reproduction:

{
  "declared_url": "app%20part.js.map",
  "declared_url_sha256": "0de7bd6ac02a3e17ee549499a516e2de08262a4fe7b40a728fa209df6d806863",
  "resolved_path": null,
  "available": false
}

The same graph contains an inventory observation with path: "app part.js.map".

Declared URL Existing filename Actual availability
app.js.map app.js.map true
app%20part.js.map app part.js.map false
app%25part.js.map app%part.js.map false
app%2520part.js.map app%20part.js.map false
app%20part.js.map?v=1#section app part.js.map false

Typed outcome or recovery expected

An available source-map reference and maps_to edge to the existing decoded local file, retaining the raw declaration's identity. Existing malformed-encoding, encoded-separator/dot/NUL, external-URL, and confinement outcomes should remain explicit.

Analysis or suspected cause

Source-derived cause, consistent with the public reproductions: contextualCandidate strips query/fragment for url-reference but passes the still-encoded local path to relativeCandidate. HTML URL and ESM URL branches already have URL decoding. Source-map discovery uses url-reference.

Decode only the local lookup path once; changing the persisted declared URL would lose caller/source evidence, and repeated decoding would confuse %2520 with a space filename.

Additional context

An independent read-only review checked the encoded-asterisk public reproduction and resolver branch. Four further public CLI fixtures confirmed spaces, literal percent, single-decode semantics, and query/fragment handling. A regression should use the real artifact workflow and retain existing URL rejection and exact-identity coverage. The current url-reference tests cover ordinary sibling paths, query/fragment, and external URLs, with no percent-encoded local filename case.

Originally created by @N0zoM1z0 on GitHub (Oct 11, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/1782 ### 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 `analyze-javascript-application` retains a percent-encoded source-map URL correctly but fails to resolve it to the existing local source-map filename. For `//# sourceMappingURL=app%20part.js.map`, the graph inventories `app part.js.map` yet records its reference as `resolved_path: null`, `available: false`. The public CLI also fails for `%25` (literal percent), `%2520` (a filename containing the literal text `%20`, requiring exactly one decode), and an encoded-space URL with query/fragment suffixes. Ordinary unencoded sibling paths resolve successfully. ### Reproduction 1. Build revision `914ba833ded5f8604345de4e4f6d306de0a38c4e` using the pinned toolchain: `npm ci` and `npm run build:cached`. 2. Generate this small local fixture with Node: ```js import { mkdtempSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; const root = mkdtempSync(join(tmpdir(), 'rea-map-encoding-')); writeFileSync(join(root, 'app.js'), 'export const value=1;\n//# sourceMappingURL=app%20part.js.map\n'); writeFileSync(join(root, 'app part.js.map'), JSON.stringify({version: 3, file: 'app.js', sources: [], names: [], mappings: ''})); console.log(root); ``` 3. Run `node scripts/rea.mjs analyze-javascript-application /tmp/PRINTED-DIRECTORY --max-heap-mb 512 --json`. 4. Inspect `normalized_result.graph`: the reference is unavailable even though the exact decoded local map is inventoried. ### Expected behavior Use URL path semantics for local source-map lookup: decode the path once, normalize/confine it at the owning boundary, and resolve the selected local file. Preserve the original `declared_url`, its digest, and its source location. Query and fragment text should not become filesystem filename components. ### Impact and scope Source-map linkage is lost for valid URL-encoded local filenames, including ordinary spaces. Verified through the public CLI with tiny local fixtures; all runs exit `0` with complete graph coverage. This is independent of directive-token extraction: the full encoded declaration is already present in the failing output. Other consumers of the shared `url-reference` resolver have not been runtime-tested in this report. ### REA version 6.4.0 source build, commit `914ba833ded5f8604345de4e4f6d306de0a38c4e`. ### Runtime and platform Linux x64; Node.js 24.18.0; npm 11.16.0. CLI probes ran serially on one CPU, with 512 MiB Node/analysis-worker heaps. Native Windows/macOS execution was not tested; no native provider is needed. ### Target and artifact context Source-owned JavaScript module and valid empty v3 source-map file in a temporary directory. No external URL fetching, target execution, or sensitive artifacts involved. ### Interface CLI ### Earliest failure stage Artifact or evidence registration ### Relevant output or evidence For the `%20` reproduction: ```json { "declared_url": "app%20part.js.map", "declared_url_sha256": "0de7bd6ac02a3e17ee549499a516e2de08262a4fe7b40a728fa209df6d806863", "resolved_path": null, "available": false } ``` The same graph contains an inventory observation with `path: "app part.js.map"`. | Declared URL | Existing filename | Actual availability | | --- | --- | --- | | `app.js.map` | `app.js.map` | true | | `app%20part.js.map` | `app part.js.map` | false | | `app%25part.js.map` | `app%part.js.map` | false | | `app%2520part.js.map` | `app%20part.js.map` | false | | `app%20part.js.map?v=1#section` | `app part.js.map` | false | ### Typed outcome or recovery expected An available source-map reference and `maps_to` edge to the existing decoded local file, retaining the raw declaration's identity. Existing malformed-encoding, encoded-separator/dot/NUL, external-URL, and confinement outcomes should remain explicit. ### Analysis or suspected cause Source-derived cause, consistent with the public reproductions: [`contextualCandidate`](https://github.com/morluto/rea/blob/914ba833ded5f8604345de4e4f6d306de0a38c4e/src/application/javascript/JavaScriptArtifactPathResolution.ts#L136-L178) strips query/fragment for `url-reference` but passes the still-encoded local path to `relativeCandidate`. HTML URL and ESM URL branches already have URL decoding. Source-map discovery [uses `url-reference`](https://github.com/morluto/rea/blob/914ba833ded5f8604345de4e4f6d306de0a38c4e/src/application/javascript/JavaScriptArtifactGraphFindings.ts#L300-L317). Decode only the local lookup path once; changing the persisted declared URL would lose caller/source evidence, and repeated decoding would confuse `%2520` with a space filename. ### Additional context An independent read-only review checked the encoded-asterisk public reproduction and resolver branch. Four further public CLI fixtures confirmed spaces, literal percent, single-decode semantics, and query/fragment handling. A regression should use the real artifact workflow and retain existing URL rejection and exact-identity coverage. The current `url-reference` tests cover ordinary sibling paths, query/fragment, and external URLs, with no percent-encoded local filename case.
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#600
No description provided.