From 15e17ea1398de7217dd8745d15be446aa39cd3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6ssler?= Date: Mon, 20 Jan 2025 09:40:34 +0100 Subject: [PATCH 1/3] Support fetch(new Request(...)) --- library/sinks/Fetch.test.ts | 12 +++++++++++- library/sinks/Fetch.ts | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/library/sinks/Fetch.test.ts b/library/sinks/Fetch.test.ts index 054f689f4..a3a2be466 100644 --- a/library/sinks/Fetch.test.ts +++ b/library/sinks/Fetch.test.ts @@ -105,6 +105,14 @@ t.test( t.same(agent.getHostnames().asArray(), []); agent.getHostnames().clear(); + await fetch(new Request("https://app.aikido.dev")); + + t.same(agent.getHostnames().asArray(), [ + { hostname: "app.aikido.dev", port: 443, hits: 1 }, + ]); + + agent.getHostnames().clear(); + await runWithContext(context, async () => { // Don't await fetch to see how it handles // multiple requests at the same time @@ -258,7 +266,9 @@ t.test( ...{ body: { image: redirectUrl.domainTwice } }, }, async () => { - const error = await t.rejects(() => fetch(redirectUrl.domainTwice)); + const error = await t.rejects(() => + fetch(new Request(redirectUrl.domainTwice)) + ); if (error instanceof Error) { t.same( // @ts-expect-error Type is not defined diff --git a/library/sinks/Fetch.ts b/library/sinks/Fetch.ts index 730bb1ce7..f0924fe7d 100644 --- a/library/sinks/Fetch.ts +++ b/library/sinks/Fetch.ts @@ -79,6 +79,20 @@ export class Fetch implements Wrapper { return attack; } } + + if (args[0] instanceof Request) { + const url = tryParseURL(args[0].url); + if (url) { + const attack = this.inspectHostname( + agent, + url.hostname, + getPortFromURL(url) + ); + if (attack) { + return attack; + } + } + } } return undefined; From 6477fcdc096c090fa77d2b8bd73c033f4282a1d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6ssler?= Date: Mon, 20 Jan 2025 09:44:57 +0100 Subject: [PATCH 2/3] Fix linting --- library/sinks/Fetch.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/sinks/Fetch.ts b/library/sinks/Fetch.ts index f0924fe7d..11a4f1576 100644 --- a/library/sinks/Fetch.ts +++ b/library/sinks/Fetch.ts @@ -1,3 +1,4 @@ +/* eslint-disable max-lines-per-function */ import { lookup } from "dns"; import { Agent } from "../agent/Agent"; import { getContext } from "../agent/Context"; @@ -37,6 +38,7 @@ export class Fetch implements Wrapper { inspectFetch(args: unknown[], agent: Agent): InterceptorResult { if (args.length > 0) { + // URL string if (typeof args[0] === "string" && args[0].length > 0) { const url = tryParseURL(args[0]); if (url) { @@ -69,6 +71,7 @@ export class Fetch implements Wrapper { } } + // URL object if (args[0] instanceof URL && args[0].hostname.length > 0) { const attack = this.inspectHostname( agent, @@ -80,6 +83,7 @@ export class Fetch implements Wrapper { } } + // Request object if (args[0] instanceof Request) { const url = tryParseURL(args[0].url); if (url) { From 0c47d31a987287e4331f29e5e0b2f07e8c55a217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6ssler?= Date: Mon, 20 Jan 2025 09:59:48 +0100 Subject: [PATCH 3/3] Improve code coverage --- library/sinks/Fetch.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/library/sinks/Fetch.test.ts b/library/sinks/Fetch.test.ts index a3a2be466..55ee6063c 100644 --- a/library/sinks/Fetch.test.ts +++ b/library/sinks/Fetch.test.ts @@ -164,6 +164,16 @@ t.test( "Zen has blocked a server-side request forgery: fetch(...) originating from body.image" ); } + + const error4 = await t.rejects(() => + fetch(new Request("http://localhost:4000/api/internal")) + ); + if (error4 instanceof Error) { + t.same( + error4.message, + "Zen has blocked a server-side request forgery: fetch(...) originating from body.image" + ); + } }); await runWithContext(