Skip to content

Commit 185007a

Browse files
committed
fix(knowledge): prevent SSRF bypass via hostname prefix matching on domain names
1 parent 8445d7e commit 185007a

File tree

1 file changed

+17
-12
lines changed

1 file changed

+17
-12
lines changed

apps/sim/app/api/knowledge/route.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,25 @@ const CreateKnowledgeBaseSchema = z.object({
6262
if (hostname.startsWith('[') && hostname !== '[::1]') {
6363
return false
6464
}
65-
// Allow localhost, loopback, and private network ranges
66-
if (
67-
hostname === 'localhost' ||
68-
hostname === '[::1]' ||
69-
hostname.startsWith('127.') ||
70-
hostname.startsWith('10.') ||
71-
hostname.startsWith('192.168.')
72-
) {
65+
// Allow localhost and IPv6 loopback
66+
if (hostname === 'localhost' || hostname === '[::1]') {
7367
return true
7468
}
75-
// Allow 172.16.0.0 – 172.31.255.255
76-
if (hostname.startsWith('172.')) {
77-
const second = Number.parseInt(hostname.split('.')[1], 10)
78-
if (second >= 16 && second <= 31) return true
69+
// Allow private IPv4 ranges — only match actual IPs, not domains like "10.evil.com"
70+
const ipv4 = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
71+
if (ipv4.test(hostname)) {
72+
if (
73+
hostname.startsWith('127.') ||
74+
hostname.startsWith('10.') ||
75+
hostname.startsWith('192.168.')
76+
) {
77+
return true
78+
}
79+
if (hostname.startsWith('172.')) {
80+
const second = Number.parseInt(hostname.split('.')[1], 10)
81+
if (second >= 16 && second <= 31) return true
82+
}
83+
return false
7984
}
8085
// Allow Docker service hostnames (no dots = not a public domain)
8186
// e.g. "ollama", "host.docker.internal"

0 commit comments

Comments
 (0)