Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions library/agent/Source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const SOURCES = [
"xml",
"subdomains",
"markUnsafe",
"url",
] as const;

export type Source = (typeof SOURCES)[number];
63 changes: 62 additions & 1 deletion library/sources/HTTPServer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import { mkdtemp, writeFile, unlink } from "fs/promises";
import { exec } from "child_process";
import { promisify } from "util";
import { FileSystem } from "../sinks/FileSystem";
import { Path } from "../sinks/Path";
const execAsync = promisify(exec);

// Before require("http")
Expand Down Expand Up @@ -48,7 +50,7 @@
token: new Token("123"),
api,
});
agent.start([new HTTPServer()]);
agent.start([new HTTPServer(), new FileSystem(), new Path()]);

wrap(fetchBlockedLists, "fetchBlockedLists", function fetchBlockedLists() {
return async function fetchBlockedLists(): Promise<{
Expand Down Expand Up @@ -78,6 +80,7 @@

const http = require("http") as typeof import("http");
const https = require("https") as typeof import("https");
const { readFileSync } = require("fs");

t.test("it wraps the createServer function of http module", async () => {
const server = http.createServer((req, res) => {
Expand Down Expand Up @@ -719,3 +722,61 @@
});
}
);

t.test("it blocks path traversal in path", async (t) => {
const server = http.createServer((req, res) => {
try {
// @ts-expect-error Ignore
const file = readFileSync(join(__dirname, req.url));

res.statusCode = 200;
res.end(file);
} catch (error) {
res.statusCode = 500;
if (error instanceof Error) {
res.end(error.message);
return;
}
res.end("Internal server error");
}
});

await new Promise<void>((resolve) => {
server.listen(3327, async () => {
const response = await new Promise((resolve, reject) => {
const req = http.request(
{
hostname: "localhost",
port: 3327,
path: "/../package.json", // Path traversal attempt
method: "GET",
},
(res) => {
let data = "";

res.on("data", (chunk) => {
data += chunk;
});

res.on("end", () => {
resolve(data);
});
}
);

req.on("error", (err) => {
reject(err);
});

req.end();
});

t.equal(
response,
"Zen has blocked a path traversal attack: path.join(...) originating from url."
);
server.close();
resolve();
});
});
});
Loading