Reject dot segments in asset URLs

This commit is contained in:
scamiv
2026-03-23 00:47:55 +01:00
parent f3f41f68d0
commit 110dcc2e54
2 changed files with 23 additions and 1 deletions
+14 -1
View File
@@ -8,6 +8,19 @@ function safeDecodeAssetSegment(segment: string): string {
}
}
function assertSafeAssetSegment(segment: string): string {
const decodedSegment = safeDecodeAssetSegment(segment);
if (
segment === "." ||
segment === ".." ||
decodedSegment === "." ||
decodedSegment === ".."
) {
throw new Error(`Invalid asset path segment: ${segment}`);
}
return decodedSegment;
}
export function encodeAssetPath(path: string): string {
return normalizeAssetPath(path)
.split("/")
@@ -21,7 +34,7 @@ export function normalizeAssetPath(path: string): string {
.replace(/^\/+/, "")
.split("/")
.filter((segment) => segment.length > 0)
.map((segment) => safeDecodeAssetSegment(segment))
.map((segment) => assertSafeAssetSegment(segment))
.join("/");
}
+9
View File
@@ -27,4 +27,13 @@ describe("AssetUrls", () => {
test("falls back to the unversioned path when manifest has no match", () => {
expect(buildAssetUrl("images/unknown.svg", {})).toBe("/images/unknown.svg");
});
test("rejects dot segments in asset paths", () => {
expect(() => buildAssetUrl("../api/instance", {})).toThrow(
"Invalid asset path segment: ..",
);
expect(() => buildAssetUrl("images/%2e%2e/secret.svg", {})).toThrow(
"Invalid asset path segment: %2e%2e",
);
});
});