Conversation
- Introduced ScrollArea for better content management. - Applied text-xs for smaller font sizes in various elements. - Refined button styles and spacing.
Comment on lines
+90
to
+99
| const webhookResponse = await fetch(destinationUrl, { | ||
| method: 'POST', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| // --- PAYLOAD INTEGRITY DEFENSE --- | ||
| 'X-Webhook-Secret': secretKey, | ||
| 'User-Agent': 'AICAP-Webhook-Dispatcher/1.0', | ||
| }, | ||
| body: JSON.stringify(payload), | ||
| }); |
Check failure
Code scanning / CodeQL
Server-side request forgery Critical
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 months ago
To reliably fix the SSRF vulnerability, the code should restrict outgoing requests to permitted domains using a hostname/domain allow-list rather than allowing arbitrary values from user input. This approach blocks attackers from crafting payloads targeting sensitive endpoints (internal IPs, cloud metadata URLs, etc.), even if SSRF filtering (protocol, IP blocklist) is bypassed due to logic or parsing issues.
Best way to fix:
- Implement a constant array of allowed hostnames or domains, e.g.,
const ALLOWED_HOSTNAMES = ['webhook.example.com', 'hooks.mydomain.app']. - When parsing
destinationUrl, check thaturl.hostnameis present in (or a valid subdomain below) one of these permitted hostnames. - If the check fails, return a 403 (Forbidden) error.
- This change should be made in the logic before the fetch() request (after parsing the input, before SSRF defenses and network call).
- It's important to communicate rejection with a clear error message.
Required additions:
- Add the
ALLOWED_HOSTNAMESarray near the top of the file (region before POST). - Add logic after parsing the URL (
url = new URL(...)) but before the SSRF defenses, e.g. after line 48.
Suggested changeset
1
app/api/execute-webhook/route.ts
| @@ -2,6 +2,12 @@ | ||
| import { URL } from 'url'; | ||
| import { promises as dns } from 'dns'; | ||
|
|
||
| // SSRF FIX: Only allow requests to approved hostnames/domains | ||
| const ALLOWED_HOSTNAMES = [ | ||
| 'webhook.example.com', | ||
| 'hooks.mydomain.app', | ||
| // Add more allowed hostnames/domains as needed | ||
| ]; | ||
| // Helper function to resolve the IP address of a hostname | ||
| async function resolveIP(hostname) { | ||
| try { | ||
| @@ -46,6 +52,15 @@ | ||
| return Response.json({ success: false, error: 'Invalid destination URL format.' }, { status: 400 }); | ||
| } | ||
|
|
||
| // SSRF FIX: Check host against allowlist | ||
| const hostnameIsAllowed = ALLOWED_HOSTNAMES.some(allowed => url.hostname === allowed || url.hostname.endsWith('.' + allowed)); | ||
| if (!hostnameIsAllowed) { | ||
| return Response.json({ | ||
| success: false, | ||
| error: `Target hostname "${url.hostname}" is not allowed by server SSRF policy.` | ||
| }, { status: 403 }); | ||
| } | ||
|
|
||
| // 2. --- SSRF DEFENSE 1: PROTOCOL LOCK --- | ||
| if (url.protocol !== 'https:') { | ||
| return Response.json({ success: false, error: 'Protocol violation. Only HTTPS endpoints are permitted for security reasons.' }, { status: 403 }); |
Copilot is powered by AI and may make mistakes. Always verify output.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.