[PR #1287] [MERGED] fix(javascript): resolve HTML script URLs after URL whitespace and percent decoding #2769

Closed
opened 2026-10-17 21:10:01 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1287
Author: @kaoru0822-kitauji
Created: 10/9/2026
Status: ✅ Merged
Merged: 10/9/2026
Merged by: @kaoru0822-kitauji

Base: main ← Head: fix/javascript-html-script-url-decoding


📝 Commits (1)

  • 502528c fix(javascript): resolve HTML script URLs after URL whitespace and percent decoding

📊 Changes

5 files changed (+156 additions, -10 deletions)

View changed files

📝 docs/javascript-artifact-reconstruction.md (+5 -2)
📝 src/application/javascript/JavaScriptArtifactPathResolution.ts (+20 -8)
📝 src/application/javascript/JavaScriptHtmlBaseResolution.test.ts (+64 -0)
📝 src/domain/artifactPathSyntax.ts (+49 -0)
📝 tests/boundary/filesystem/javascriptHtmlResourcePaths.test.ts (+18 -0)

📄 Description

Summary

analyze_javascript_application looked up an HTML <script src> and <base href> literally, so a script URL with percent-encoded letters (%61pp.js), surrounding whitespace (" app.js "), or an encoded local base (%61ssets/) was reported as not-found even though the exact file was inventoried. The renderer-to-script loads edge was then missing from the graph.

Closes #1236

Change

  • htmlCandidate now reads the script URL and base href the way a browser does: HTML strips surrounding ASCII whitespace and the URL parser strips surrounding C0 controls/spaces and removes embedded tabs and newlines (htmlUrlText).
  • The path parts are then percent-decoded as the URL standard does (percentDecodeUrlPath): valid %XX sequences become bytes, any other % stays literal (so 100%.js behaves as before).
  • Encoded dot and separator bytes (%2e, %2f, %5c) are still refused before decoding, so decoding adds no path segments. Paths that decode to NUL or to non-UTF-8 bytes return rejected with a limitation naming that constraint.
  • Leading whitespace no longer hides an external URL: " https://…" is now reported as external instead of being looked up as a local path.
  • The raw declaration stays in declared_path / script_path as evidence.

Both helpers live in src/domain/artifactPathSyntax.ts next to the existing path syntax predicates.

Verification

  • npm run check:changed (28 files, 495 tests)
  • npm run test:focused -- tests/boundary/filesystem/javascriptHtmlResourcePaths.test.ts: the three new issue cases fail on main and pass here
  • New unit cases compare each resolution with native new URL(...) pathname decoding
  • npx tsc --noEmit, npm run docs:check
  • Real CLI on the three issue fixtures (node scripts/rea.mjs analyze-javascript-application DIR --format json): every reference now reports resolved (app.js, app.js, assets/app.js)

No Hopper/Ghidra involvement.

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/1287 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/9/2026 **Status:** ✅ Merged **Merged:** 10/9/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `fix/javascript-html-script-url-decoding` --- ### 📝 Commits (1) - [`502528c`](https://github.com/morluto/rea/commit/502528c58df54c7b34eefdb5837f36e58f473405) fix(javascript): resolve HTML script URLs after URL whitespace and percent decoding ### 📊 Changes **5 files changed** (+156 additions, -10 deletions) <details> <summary>View changed files</summary> 📝 `docs/javascript-artifact-reconstruction.md` (+5 -2) 📝 `src/application/javascript/JavaScriptArtifactPathResolution.ts` (+20 -8) 📝 `src/application/javascript/JavaScriptHtmlBaseResolution.test.ts` (+64 -0) 📝 `src/domain/artifactPathSyntax.ts` (+49 -0) 📝 `tests/boundary/filesystem/javascriptHtmlResourcePaths.test.ts` (+18 -0) </details> ### 📄 Description ## Summary `analyze_javascript_application` looked up an HTML `<script src>` and `<base href>` literally, so a script URL with percent-encoded letters (`%61pp.js`), surrounding whitespace (`" app.js "`), or an encoded local base (`%61ssets/`) was reported as `not-found` even though the exact file was inventoried. The renderer-to-script `loads` edge was then missing from the graph. Closes #1236 ## Change - `htmlCandidate` now reads the script URL and base href the way a browser does: HTML strips surrounding ASCII whitespace and the URL parser strips surrounding C0 controls/spaces and removes embedded tabs and newlines (`htmlUrlText`). - The path parts are then percent-decoded as the URL standard does (`percentDecodeUrlPath`): valid `%XX` sequences become bytes, any other `%` stays literal (so `100%.js` behaves as before). - Encoded dot and separator bytes (`%2e`, `%2f`, `%5c`) are still refused before decoding, so decoding adds no path segments. Paths that decode to NUL or to non-UTF-8 bytes return `rejected` with a limitation naming that constraint. - Leading whitespace no longer hides an external URL: `" https://…"` is now reported as `external` instead of being looked up as a local path. - The raw declaration stays in `declared_path` / `script_path` as evidence. Both helpers live in `src/domain/artifactPathSyntax.ts` next to the existing path syntax predicates. ## Verification - `npm run check:changed` (28 files, 495 tests) - `npm run test:focused -- tests/boundary/filesystem/javascriptHtmlResourcePaths.test.ts`: the three new issue cases fail on `main` and pass here - New unit cases compare each resolution with native `new URL(...)` pathname decoding - `npx tsc --noEmit`, `npm run docs:check` - Real CLI on the three issue fixtures (`node scripts/rea.mjs analyze-javascript-application DIR --format json`): every reference now reports `resolved` (`app.js`, `app.js`, `assets/app.js`) No Hopper/Ghidra involvement. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-17 21:10:01 +00:00
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#2769
No description provided.