Skip to content

Commit 36520e2

Browse files
waleedlatif1claude
andcommitted
fix(agiloft): add SSRF protection via DNS validation on instanceUrl
Validates user-supplied instanceUrl against private/reserved IP ranges using validateUrlWithDNS before making any outbound requests. Uses dynamic import to avoid bundling Node.js dns module in client-side code. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a835858 commit 36520e2

1 file changed

Lines changed: 23 additions & 0 deletions

File tree

apps/sim/tools/agiloft/utils.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createLogger } from '@sim/logger'
2+
import { validateExternalUrl } from '@/lib/core/security/input-validation'
23
import type {
34
AgiloftAttachmentInfoParams,
45
AgiloftBaseParams,
@@ -22,6 +23,26 @@ interface AgiloftRequestConfig {
2223
body?: BodyInit
2324
}
2425

26+
/**
27+
* Validates an Agiloft instance URL against SSRF attacks.
28+
* Performs synchronous URL format checks and async DNS resolution
29+
* to block requests to private/reserved IP addresses.
30+
*/
31+
async function validateAgiloftUrl(instanceUrl: string): Promise<void> {
32+
const basicValidation = validateExternalUrl(instanceUrl, 'instanceUrl')
33+
if (!basicValidation.isValid) {
34+
throw new Error(`Invalid Agiloft instance URL: ${basicValidation.error}`)
35+
}
36+
37+
// Dynamic import to avoid bundling Node.js dns module in client code.
38+
// This function is only called from directExecution (server-side).
39+
const { validateUrlWithDNS } = await import('@/lib/core/security/input-validation.server')
40+
const dnsValidation = await validateUrlWithDNS(instanceUrl, 'instanceUrl')
41+
if (!dnsValidation.isValid) {
42+
throw new Error(`Agiloft instance URL blocked: ${dnsValidation.error}`)
43+
}
44+
}
45+
2546
/**
2647
* Exchanges login/password for a short-lived Bearer token via EWLogin.
2748
*/
@@ -32,6 +53,8 @@ async function agiloftLogin(params: AgiloftBaseParams): Promise<string> {
3253
throw new Error('Agiloft instanceUrl must use HTTPS to protect credentials')
3354
}
3455

56+
await validateAgiloftUrl(params.instanceUrl)
57+
3558
const kb = encodeURIComponent(params.knowledgeBase)
3659
const login = encodeURIComponent(params.login)
3760
const password = encodeURIComponent(params.password)

0 commit comments

Comments
 (0)