fix(backend): close two SSRF bypasses in webhook URL validation
1. The URL guard only classified IP-literal hostnames; any plain domain name (the common case) skipped validation entirely. Hostnames are now resolved via DNS and every returned address is checked against the same private/loopback/link-local ranges (net.BlockList), so an attacker-controlled domain pointed at an internal IP is rejected too. 2. fetch() follows redirects by default, so a registered public URL could 302 to an internal target at delivery time. Delivery now uses redirect: 'manual' so such a redirect is never followed.
This commit is contained in:
1 parent
a0f7573af5
commit
79010a926b
4 files changed
+157
-71
No files matched your search
@@ -45,7 +45,7 @@ describe('WebhooksService', () => {
|
||||
);
|
||||
|
||||
const subscription = await service.create(
|
||||
{ url: 'https://example.test/hook', events: ['colony.created'] },
|
||||
{ url: 'https://203.0.113.10/hook', events: ['colony.created'] },
|
||||
'user-1',
|
||||
);
|
||||
|
||||
@@ -53,7 +53,7 @@ describe('WebhooksService', () => {
|
||||
const [[createArg]] = prisma.webhookSubscription.create.mock.calls as [
|
||||
[{ data: { url: string; events: string[]; createdByUserId: string } }],
|
||||
];
|
||||
expect(createArg.data.url).toBe('https://example.test/hook');
|
||||
expect(createArg.data.url).toBe('https://203.0.113.10/hook');
|
||||
expect(createArg.data.events).toEqual(['colony.created']);
|
||||
expect(createArg.data.createdByUserId).toBe('user-1');
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user