summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Casonato <lucacasonato@yahoo.com>2020-10-27 11:48:45 +0100
committerGitHub <noreply@github.com>2020-10-27 11:48:45 +0100
commit30f3b831d31ec47e7d120bcd34194b7b69e6f716 (patch)
tree6affbc6923ed9cd07f87960d19ab0dab35c9d921
parent9fb4931a95e551c689d4f8ed5d7304f64aafc4d0 (diff)
fix: path traversal in std/http/file_server.ts (#8134)
-rw-r--r--std/http/file_server.ts5
-rw-r--r--std/http/file_server_test.ts37
2 files changed, 39 insertions, 3 deletions
diff --git a/std/http/file_server.ts b/std/http/file_server.ts
index e4c8c4931..b75f9f9c1 100644
--- a/std/http/file_server.ts
+++ b/std/http/file_server.ts
@@ -322,14 +322,15 @@ function html(strings: TemplateStringsArray, ...values: unknown[]): string {
}
function normalizeURL(url: string): string {
- let normalizedUrl = posix.normalize(url);
+ let normalizedUrl = url;
try {
- normalizedUrl = decodeURIComponent(normalizedUrl);
+ normalizedUrl = decodeURI(normalizedUrl);
} catch (e) {
if (!(e instanceof URIError)) {
throw e;
}
}
+ normalizedUrl = posix.normalize(normalizedUrl);
const startOfParams = normalizedUrl.indexOf("?");
return startOfParams > -1
? normalizedUrl.slice(0, startOfParams)
diff --git a/std/http/file_server_test.ts b/std/http/file_server_test.ts
index 3368b2e15..ca8d3b3b2 100644
--- a/std/http/file_server_test.ts
+++ b/std/http/file_server_test.ts
@@ -1,5 +1,9 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import { assert, assertEquals } from "../testing/asserts.ts";
+import {
+ assert,
+ assertEquals,
+ assertStringIncludes,
+} from "../testing/asserts.ts";
import { BufReader } from "../io/bufio.ts";
import { TextProtoReader } from "../textproto/mod.ts";
import { ServerRequest } from "./server.ts";
@@ -147,6 +151,37 @@ Deno.test("serveFallback", async function (): Promise<void> {
}
});
+Deno.test("checkPathTraversal", async function (): Promise<void> {
+ await startFileServer();
+ try {
+ const res = await fetch(
+ "http://localhost:4507/../../../../../../../..",
+ );
+ assert(res.headers.has("access-control-allow-origin"));
+ assert(res.headers.has("access-control-allow-headers"));
+ assertEquals(res.status, 200);
+ const listing = await res.text();
+ assertStringIncludes(listing, "README.md");
+ } finally {
+ await killFileServer();
+ }
+});
+
+Deno.test("checkURIEncodedPathTraversal", async function (): Promise<void> {
+ await startFileServer();
+ try {
+ const res = await fetch(
+ "http://localhost:4507/%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..",
+ );
+ assert(res.headers.has("access-control-allow-origin"));
+ assert(res.headers.has("access-control-allow-headers"));
+ assertEquals(res.status, 404);
+ const _ = await res.text();
+ } finally {
+ await killFileServer();
+ }
+});
+
Deno.test("serveWithUnorthodoxFilename", async function (): Promise<void> {
await startFileServer();
try {