/** * @module @arcis/node/validation/url * SSRF (Server-Side Request Forgery) prevention * * Validates URLs to ensure they don't target private/internal networks, * localhost, cloud metadata endpoints, or use dangerous protocols. * * @example * import { validateUrl } from '@arcis/node'; * * // Block SSRF attempts * validateUrl('http://169.254.169.254/latest/meta-data/') // { safe: false, reason: 'link-local address' } * validateUrl('http://10.0.0.1/admin') // { safe: false, reason: 'private address (10.0.0.0/8)' } * validateUrl('http://localhost/secret') // { safe: false, reason: 'loopback address' } * validateUrl('file:///etc/passwd') // { safe: false, reason: 'disallowed protocol: file:' } * * // Allow safe URLs * validateUrl('https://api.example.com/data') // { safe: true } */ /** Options for URL validation */ export interface ValidateUrlOptions { /** Allowed protocols. Default: ['http:', 'https:'] */ allowedProtocols?: string[]; /** Additional hostnames to block (e.g., internal service names) */ blockedHosts?: string[]; /** Additional hostnames to always allow (bypass IP checks) */ allowedHosts?: string[]; /** Allow localhost/loopback. Default: false */ allowLocalhost?: boolean; /** Allow private/internal IPs. Default: false */ allowPrivate?: boolean; } /** Result of URL validation */ export interface ValidateUrlResult { /** Whether the URL is safe to fetch */ safe: boolean; /** Reason the URL was blocked (only set when safe=false) */ reason?: string; } /** * Validate a URL for SSRF safety. * * Checks: * 1. Valid URL format * 2. Allowed protocol (default: http, https only) * 3. Not localhost/loopback (127.x.x.x, ::1, localhost) * 4. Not private IP (10.x, 172.16-31.x, 192.168.x) * 5. Not link-local (169.254.x.x — includes AWS/GCP/Azure metadata) * 6. Not blocked hostname * 7. No credentials in URL (user:pass@host) * * @param url - The URL string to validate * @param options - Validation options * @returns Validation result with safe flag and optional reason */ export declare function validateUrl(url: string, options?: ValidateUrlOptions): ValidateUrlResult; /** * Convenience wrapper that returns true/false. * * @param url - The URL to check * @param options - Validation options * @returns true if the URL is safe to fetch */ export declare function isUrlSafe(url: string, options?: ValidateUrlOptions): boolean; /** Result of scanning a request body for SSRF-shaped URL values. */ export interface SsrfScanResult { /** True if any URL-shaped string value failed validation. */ detected: boolean; /** The offending URL string, or null. */ url: string | null; /** Why it was blocked (from validateUrl), or null. */ reason: string | null; } /** * Recursively walk a parsed request body and run `validateUrl` on every * string value that looks like a URL (`scheme://...`). Returns the first * unsafe URL found. v1.7 W5 wire-up. * * Public URLs pass, so a body carrying `{ website: "https://example.com" }` * is not blocked; only private / loopback-IP / link-local / metadata / * file-read-scheme URLs trip it. See `SSRF_BODY_SCAN_PROTOCOLS` for the * scheme + localhost policy. * * @param body - Parsed request body (object, array, or scalar). * @param options - Forwarded to `validateUrl`. When `allowedProtocols` * is not set, the body-scan profile (http/https/ftp/ftps) is used. * @param maxDepth - Max recursion depth. Default 8. */ export declare function scanForSsrf(body: unknown, options?: ValidateUrlOptions, maxDepth?: number): SsrfScanResult; //# sourceMappingURL=url.d.ts.map