taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 510a87fe34e9d435af480458ab9e22be5ad64c56
parent dc9ac3bdaf8525ae458ac38905e34b159b1628a1
Author: Florian Dold <dold@taler.net>
Date:   Tue, 21 Jul 2026 11:07:14 +0200

util: escape tab, LF and CR in taler URI path components

The URL parser removes those three before parsing, so ".." followed by a
tab passed the dot-segment guard and then became one inside the parser,
letting a merchant order id erase the merchant host.

Diffstat:
Mpackages/taler-util/src/taleruri.ts | 16++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/packages/taler-util/src/taleruri.ts b/packages/taler-util/src/taleruri.ts @@ -238,9 +238,9 @@ export namespace TalerUris { return result; } case TalerUriAction.DevExperiment: { - Object.entries(p.query ?? {}).forEach(([key,value])=> { - result.push([key,value]) - }) + Object.entries(p.query ?? {}).forEach(([key, value]) => { + result.push([key, value]); + }); return result; } case TalerUriAction.Refund: @@ -458,7 +458,8 @@ export namespace TalerUris { }); } - const targetPath = firstSlashPos === -1 ? "" : path.slice(firstSlashPos + 1); + const targetPath = + firstSlashPos === -1 ? "" : path.slice(firstSlashPos + 1); // withdrawal-transfer-result carries all its data in query parameters and // so legitimately has no path. if ( @@ -1168,9 +1169,12 @@ function encodeUriSegment(s: string): string { } // Only the characters that would break the positional/query parsing are // escaped, so that components without them keep their on-the-wire form. + // Tab, LF and CR are among them because the URL parser removes them before + // parsing, which would otherwise turn "..\t" back into a dot segment. return s.replace( - /[%/?#]/g, - (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`, + // eslint-disable-next-line no-control-regex + /[%/?#\t\n\r]/g, + (c) => `%${c.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`, ); }