fix(auth): address review — reject a query or fragment in the metadata path

`isOriginRelativePath` compared the resolved href against the literal, which
`URL` preserves a query and fragment in — so `/doc?version=1` and `/doc#section`
passed. Express matches on the path alone (and treats `?` as a pattern
character), and a fragment never reaches the server, so the advertised URL
could not resolve to the registered route. Reject both, with cases added to
the table-driven test.

Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-24 20:36:39 -04:00
commit 8beba25b58

View file

@ -40,6 +40,12 @@ const PATH_VALIDATION_BASE = "http://config.invalid";
* it does not serve (Copilot). Comparing the resolved href against the literal
* also rejects anything the parser would rewrite (spaces, unescaped
* characters), which an Express route would not match either.
*
* A query or fragment is rejected for the same reason from the other
* direction: `href` preserves both, so `/doc?v=1` and `/doc#s` would pass the
* comparison above, yet Express matches on the path alone (and treats `?` as a
* pattern character) and a fragment is never sent on the wire at all — so the
* advertised URL could not reach the registered route (Copilot).
*/
export function isOriginRelativePath(value: unknown): value is string {
if (typeof value !== "string" || !value.startsWith("/")) {
@ -49,6 +55,8 @@ export function isOriginRelativePath(value: unknown): value is string {
const resolved = new URL(value, PATH_VALIDATION_BASE);
return (
resolved.origin === PATH_VALIDATION_BASE &&
resolved.search === "" &&
resolved.hash === "" &&
resolved.href === `${PATH_VALIDATION_BASE}${value}`
);
} catch {