Skip to content

Commit f80214c

Browse files
authored
Merge pull request #504 from AikidoSec/fix-fetch-new-request
Support fetch(new Request(...))
2 parents 588f93b + 0c47d31 commit f80214c

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

library/sinks/Fetch.test.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,14 @@ t.test(
105105
t.same(agent.getHostnames().asArray(), []);
106106
agent.getHostnames().clear();
107107

108+
await fetch(new Request("https://app.aikido.dev"));
109+
110+
t.same(agent.getHostnames().asArray(), [
111+
{ hostname: "app.aikido.dev", port: 443, hits: 1 },
112+
]);
113+
114+
agent.getHostnames().clear();
115+
108116
await runWithContext(context, async () => {
109117
// Don't await fetch to see how it handles
110118
// multiple requests at the same time
@@ -156,6 +164,16 @@ t.test(
156164
"Zen has blocked a server-side request forgery: fetch(...) originating from body.image"
157165
);
158166
}
167+
168+
const error4 = await t.rejects(() =>
169+
fetch(new Request("http://localhost:4000/api/internal"))
170+
);
171+
if (error4 instanceof Error) {
172+
t.same(
173+
error4.message,
174+
"Zen has blocked a server-side request forgery: fetch(...) originating from body.image"
175+
);
176+
}
159177
});
160178

161179
await runWithContext(
@@ -258,7 +276,9 @@ t.test(
258276
...{ body: { image: redirectUrl.domainTwice } },
259277
},
260278
async () => {
261-
const error = await t.rejects(() => fetch(redirectUrl.domainTwice));
279+
const error = await t.rejects(() =>
280+
fetch(new Request(redirectUrl.domainTwice))
281+
);
262282
if (error instanceof Error) {
263283
t.same(
264284
// @ts-expect-error Type is not defined

library/sinks/Fetch.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable max-lines-per-function */
12
import { lookup } from "dns";
23
import { Agent } from "../agent/Agent";
34
import { getContext } from "../agent/Context";
@@ -37,6 +38,7 @@ export class Fetch implements Wrapper {
3738

3839
inspectFetch(args: unknown[], agent: Agent): InterceptorResult {
3940
if (args.length > 0) {
41+
// URL string
4042
if (typeof args[0] === "string" && args[0].length > 0) {
4143
const url = tryParseURL(args[0]);
4244
if (url) {
@@ -69,6 +71,7 @@ export class Fetch implements Wrapper {
6971
}
7072
}
7173

74+
// URL object
7275
if (args[0] instanceof URL && args[0].hostname.length > 0) {
7376
const attack = this.inspectHostname(
7477
agent,
@@ -79,6 +82,21 @@ export class Fetch implements Wrapper {
7982
return attack;
8083
}
8184
}
85+
86+
// Request object
87+
if (args[0] instanceof Request) {
88+
const url = tryParseURL(args[0].url);
89+
if (url) {
90+
const attack = this.inspectHostname(
91+
agent,
92+
url.hostname,
93+
getPortFromURL(url)
94+
);
95+
if (attack) {
96+
return attack;
97+
}
98+
}
99+
}
82100
}
83101

84102
return undefined;

0 commit comments

Comments
 (0)