hcengineering/platform · error · LinkPreviewError
INVALID_PROTOCOL
INVALID_PROTOCOL
Error message
Invalid protocol: ${url.protocol}. Only HTTP and HTTPS are allowed. What it means
validateUrl only allows http: and https: protocols as a security measure. Any other scheme (ftp:, file:, javascript:, data:, etc.) raises LinkPreviewError with code INVALID_PROTOCOL.
Source
Thrown at pods/link-preview/src/parse.ts:216
// Hostname is not an IP literal. Keep legacy explicit localhost-ish blocks.
// (We intentionally do not attempt DNS resolution here.)
if (host.endsWith('.localhost')) return true
return false
}
function validateUrl (urlString: string): URL {
let url: URL
try {
url = new URL(urlString)
} catch {
throw new LinkPreviewError(`Invalid URL: ${urlString}`, 'INVALID_URL')
}
// Only allow HTTP(S) protocols
if (!['http:', 'https:'].includes(url.protocol)) {
throw new LinkPreviewError(
`Invalid protocol: ${url.protocol}. Only HTTP and HTTPS are allowed.`,
'INVALID_PROTOCOL'
)
}
// SSRF protection: block private/internal hosts and IP literals (incl. IPv6-mapped IPv4)
if (isBlockedHost(url.hostname)) {
throw new LinkPreviewError('Blocked URL: Access to internal addresses is not allowed.', 'BLOCKED_URL')
}
return url
}
function isRedirectStatus (status: number): boolean {
return status >= 300 && status < 400
}
async function fetchWithValidatedRedirects (View on GitHub (pinned to 63e28dc964)
Solutions
- Restrict input to http(s) URLs before calling the API
- Convert supported schemes (e.g. ftp links stored as web mirrors) to https equivalents
- Reject or strip non-http(s) links at UI/ingest time
Example fix
// before
validateUrl('ftp://files.example.com/doc') // throws
// after
validateUrl('https://files.example.com/doc') Defensive patterns
Strategy: validation
Validate before calling
function isHttpProtocol(s: string): boolean {
try { const u = new URL(s.trim()); return ['http:', 'https:'].includes(u.protocol) } catch { return false }
}
if (!isHttpProtocol(input)) throw new Error('only http/https URLs are supported') Try / catch
try {
return await fetchOEmbedData(client, url)
} catch (err) {
if (err instanceof LinkPreviewError && err.code === 'INVALID_PROTOCOL') {
console.warn('unsupported protocol, skipping preview for', url); return null
}
throw err
} Prevention
- Sanitize stored links to http(s) only
- Strip or convert ftp/file/mailto links at ingest time
- Never pass raw user-supplied schemes without checking `url.protocol`
When it happens
Trigger: Passing URLs with schemes like 'file:///etc/passwd', 'ftp://...', 'javascript:alert(1)', or 'data:text/html,...' to any function that calls validateUrl.
Common situations: Stored links with ftp/file schemes from legacy data; malicious input probing for XSS/SSRF; mailto: or tel: links pasted into preview fields.
Related errors
- BLOCKED_URL
- INVALID_URL
- Failed to load server config
- getDisplayMedia not supported
- No screen access granted
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/c444ff4689d5c3c3.
Report an issue: GitHub.