Skip to content

Don't throw on malformed percent-encoding in userinfo - #243

Open
hikmetba-bit wants to merge 1 commit into
unshiftio:masterfrom
hikmetba-bit:fix/tolerant-malformed-percent-encoding-auth
Open

hikmetba-bit wants to merge 1 commit into
unshiftio:masterfrom
hikmetba-bit:fix/tolerant-malformed-percent-encoding-auth

Conversation

@hikmetba-bit

Copy link
Copy Markdown

Summary

Fixes #242.

The constructor and set('auth', ...) call encodeURIComponent(decodeURIComponent(x)) on username/password with no guard, so a stray % (or any invalid percent-escape) in the userinfo propagates a raw URIError out of new Url(...) / set(...).

new Url('http://%@example.com/'); // throws URIError: URI malformed

This contradicts url-parse's documented tolerant-parser design (see #195: "url-parse was designed to not throw errors like the legacy Node.js URL parser"), and diverges from the WHATWG URL parser, which accepts the same input without throwing.

Fix

Added a decode() helper that falls back to the raw (still-encoded) input on URIError, and used it at all six username/password call sites in the constructor and set('auth', ...). Invalid input still round-trips safely — it gets re-encoded rather than decoded (e.g. '%' becomes '%25') — it just no longer throws.

Testing

  • Added a regression test covering the constructor (http://%@example.com/, http://user:%@example.com/) and set('auth', '%').
  • Verified the new test fails with the original URIError against the code without this fix, and passes with it.
  • npm test (full mocha suite + c8 coverage): 102 passing, coverage unchanged at 100% statements / 100% lines / 100% functions.

🤖 Generated with Claude Code

The constructor and set('auth', ...) called encodeURIComponent(
decodeURIComponent(x)) on username/password with no guard, so a stray
'%' (or any invalid percent-escape) in the userinfo propagated a raw
URIError out of new Url(...) / set(...).

This contradicts url-parse's documented tolerant-parser design (unshiftio#195)
and diverges from the WHATWG URL parser, which accepts the same input
without throwing.

Add a decode() helper that falls back to the raw (still-encoded) input
on URIError, and use it at all six username/password call sites in the
constructor and set('auth'). Invalid input still round-trips safely
(re-encoded rather than decoded), it just no longer throws.

Fixes unshiftio#242.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Constructor and set('auth') throw URIError on malformed percent-encoding (WHATWG URL tolerates it)

1 participant