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

  1. Restrict input to http(s) URLs before calling the API
  2. Convert supported schemes (e.g. ftp links stored as web mirrors) to https equivalents
  3. 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

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


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/c444ff4689d5c3c3. Report an issue: GitHub.