[GH-ISSUE #2827] [Bug] HTML script URL query and fragment bytes are rejected as pathname syntax #1009

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

Originally created by @shoyann on GitHub (Oct 13, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/2827

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 rejects an HTML script reference when its query or fragment contains percent-encoded separator/dot bytes, even though its pathname names an existing selected script. The loads relationship is missing and the unresolved reference reports resolution_status: "rejected".

Reproduction

Run from a REA source checkout after npm ci && npm run build:cached:

fixture=$(mktemp -d)
printf '%s\n' '<script src="./app.js?redirect=%2Ffoo"></script>' > "$fixture/index.html"
printf '%s\n' 'globalThis.fixture = true;' > "$fixture/app.js"
node scripts/rea.mjs analyze-javascript-application "$fixture" --format json > "$fixture/result.json"
node - "$fixture/result.json" <<'NODE'
const fs = require('node:fs');
const { graph } = JSON.parse(fs.readFileSync(process.argv[2], 'utf8')).normalized_result;
console.log(JSON.stringify({
  loads: graph.edges.filter(edge => edge.relation === 'loads').map(edge => edge.properties),
  unresolved: graph.nodes.flatMap(node => node.observations)
    .filter(observation => observation.properties.mechanism === 'html-script-reference')
    .map(observation => observation.properties),
}, null, 2));
NODE

The script is only statically analyzed; it is not executed. Replacing the reference with ./app.js#route=%2Ffoo has the same failure. Replacing %2F with / makes the existing app.js resolve.

Expected behavior

Both references have pathname ./app.js. Resolve the exact selected app.js resource and retain the complete original script reference as evidence. Query and fragment bytes must not enter pathname admission. Encoded separators/dots or NUL in the actual pathname must remain rejected.

Impact and scope

Static reconstruction omits HTML-to-script relationships for otherwise valid script URLs containing encoded redirect/route values. Query-only and fragment-only references are affected too. This is a local HTML artifact resolution bug; no browser execution or network access is needed to reproduce it.

REA version

Source revision 9680da76c84a6833635dc7a5df607806d899f804.

Runtime and platform

Node.js 24.18.0, Ubuntu under WSL, Linux x64. No native analysis provider required.

Target and artifact context

A local directory containing index.html and app.js.

Interface

CLI; independently reproduced through the public stdio MCP analyze_javascript_application tool.

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

{
  "loads": [],
  "unresolved": [{
    "script_path": "./app.js?redirect=%2Ffoo",
    "resolved_path": null,
    "resolution_context": "html-reference",
    "resolution_status": "rejected",
    "limitations": ["Encoded dot or separator bytes are rejected before artifact path resolution."]
  }]
}

This excerpt omits unrelated observation properties. New compiled CLI and stdio MCP regressions both fail on the affected base because the expected loads relationship is absent.

Analysis or suspected cause

Source-derived: contextualCandidate applies generic path admission to the full HTML declaration before htmlCandidate normalizes HTML URL text and removes its query/fragment. HTML URL component handling should own admission of its normalized pathname, while preserving the original declaration in graph provenance. The existing URL-reference path already separates suffix evidence from pathname admission.

Originally created by @shoyann on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2827 ## 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` rejects an HTML script reference when its query or fragment contains percent-encoded separator/dot bytes, even though its pathname names an existing selected script. The `loads` relationship is missing and the unresolved reference reports `resolution_status: "rejected"`. ## Reproduction Run from a REA source checkout after `npm ci && npm run build:cached`: ```bash fixture=$(mktemp -d) printf '%s\n' '<script src="./app.js?redirect=%2Ffoo"></script>' > "$fixture/index.html" printf '%s\n' 'globalThis.fixture = true;' > "$fixture/app.js" node scripts/rea.mjs analyze-javascript-application "$fixture" --format json > "$fixture/result.json" node - "$fixture/result.json" <<'NODE' const fs = require('node:fs'); const { graph } = JSON.parse(fs.readFileSync(process.argv[2], 'utf8')).normalized_result; console.log(JSON.stringify({ loads: graph.edges.filter(edge => edge.relation === 'loads').map(edge => edge.properties), unresolved: graph.nodes.flatMap(node => node.observations) .filter(observation => observation.properties.mechanism === 'html-script-reference') .map(observation => observation.properties), }, null, 2)); NODE ``` The script is only statically analyzed; it is not executed. Replacing the reference with `./app.js#route=%2Ffoo` has the same failure. Replacing `%2F` with `/` makes the existing `app.js` resolve. ## Expected behavior Both references have pathname `./app.js`. Resolve the exact selected `app.js` resource and retain the complete original script reference as evidence. Query and fragment bytes must not enter pathname admission. Encoded separators/dots or NUL in the actual pathname must remain rejected. ## Impact and scope Static reconstruction omits HTML-to-script relationships for otherwise valid script URLs containing encoded redirect/route values. Query-only and fragment-only references are affected too. This is a local HTML artifact resolution bug; no browser execution or network access is needed to reproduce it. ## REA version Source revision `9680da76c84a6833635dc7a5df607806d899f804`. ## Runtime and platform Node.js 24.18.0, Ubuntu under WSL, Linux x64. No native analysis provider required. ## Target and artifact context A local directory containing `index.html` and `app.js`. ## Interface CLI; independently reproduced through the public stdio MCP `analyze_javascript_application` tool. ## Earliest failure stage Native analysis or reconstruction ## Relevant output or evidence ```json { "loads": [], "unresolved": [{ "script_path": "./app.js?redirect=%2Ffoo", "resolved_path": null, "resolution_context": "html-reference", "resolution_status": "rejected", "limitations": ["Encoded dot or separator bytes are rejected before artifact path resolution."] }] } ``` This excerpt omits unrelated observation properties. New compiled CLI and stdio MCP regressions both fail on the affected base because the expected `loads` relationship is absent. ## Analysis or suspected cause Source-derived: `contextualCandidate` applies generic path admission to the full HTML declaration before `htmlCandidate` normalizes HTML URL text and removes its query/fragment. HTML URL component handling should own admission of its normalized pathname, while preserving the original declaration in graph provenance. The existing URL-reference path already separates suffix evidence from pathname admission.
bsakaguchi 2026-10-15 18:30:19 +00:00
  • closed this issue
  • added the
    bug
    label
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#1009
No description provided.