fix: add SSRF protection for link preview and Immich URL
- Create server/src/utils/ssrfGuard.ts with checkSsrf() and createPinnedAgent()
- Resolves DNS before allowing outbound requests to catch hostnames that
map to private IPs (closes the TOCTOU gap in the old inline checks)
- Always blocks loopback (127.x, ::1) and link-local/metadata (169.254.x)
- RFC-1918, CGNAT (100.64/10), and IPv6 ULA ranges blocked by default;
opt-in via ALLOW_INTERNAL_NETWORK=true for self-hosters running Immich
on a local network
- createPinnedAgent() pins node-fetch to the validated IP, preventing
DNS rebinding between the check and the actual connection
- Replace isValidImmichUrl() (hostname-string check, no DNS resolution)
with checkSsrf(); make PUT /integrations/immich/settings async
- Audit log entry (immich.private_ip_configured) written when a user
saves an Immich URL that resolves to a private IP
- Response includes a warning field surfaced as a toast in the UI
- Replace ~20 lines of duplicated inline SSRF logic in the link-preview
handler with a single checkSsrf() call + pinned agent
- Document ALLOW_INTERNAL_NETWORK in README, docker-compose.yml,
server/.env.example, chart/values.yaml, chart/templates/configmap.yaml,
and chart/README.md
This commit is contained in:
@@ -108,6 +108,7 @@ const ACTION_LABELS: Record<string, string> = {
|
||||
'admin.user_role_change': 'changed user role',
|
||||
'admin.user_delete': 'deleted user',
|
||||
'admin.invite_create': 'created invite',
|
||||
'immich.private_ip_configured': 'configured Immich with private IP',
|
||||
};
|
||||
|
||||
/** Best-effort; never throws — failures are logged only. */
|
||||
@@ -158,6 +159,9 @@ function buildInfoSummary(action: string, details?: Record<string, unknown>): st
|
||||
if (details.require_mfa !== undefined) parts.push(`mfa=${details.require_mfa}`);
|
||||
return parts.length ? ` (${parts.join(', ')})` : '';
|
||||
}
|
||||
if (action === 'immich.private_ip_configured') {
|
||||
return details.resolved_ip ? ` url=${details.immich_url} ip=${details.resolved_ip}` : '';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user