Join the configured root with a path, tolerating a trailing slash either way.
new URL(path, base) is not used: it treats the base's last segment as a directory only when the
base ends in /, so .../betty/v1 + messages would silently resolve to .../betty/messages
and 404 against a correct deployment.
Trimmed by index rather than by //+$/ and /^/+/. Those are anchored, unbounded repetitions
over a value that arrives from configuration, which CodeQL flags as polynomial backtracking
(ReDoS) — a base of many slashes would take time quadratic in its length. Scanning from each end
is linear and cannot backtrack at all.
Join the configured root with a path, tolerating a trailing slash either way.
new URL(path, base)is not used: it treats the base's last segment as a directory only when the base ends in/, so.../betty/v1+messageswould silently resolve to.../betty/messagesand 404 against a correct deployment.Trimmed by index rather than by
//+$/and/^/+/. Those are anchored, unbounded repetitions over a value that arrives from configuration, which CodeQL flags as polynomial backtracking (ReDoS) — a base of many slashes would take time quadratic in its length. Scanning from each end is linear and cannot backtrack at all.