Skip to content

[High][Security] Use one hardened SSRF guard for OIDC and outbound webhook URLs #307

Description

@richardcmckinney

Summary

There are multiple SSRF validation implementations with different behavior. The shared SSRF guard permits http: and has an incomplete non-global IP blocklist. OIDC provider validation uses that guard even though the error message says HTTPS is required. The outbound webhook handler has its own separate private-IP regex list, misses several non-global ranges, and validates DNS but still fetches the original hostname.

Evidence

  • apps/web/src/lib/server/content/ssrf-guard.ts:23-33 allows both http: and https:.
  • apps/web/src/lib/server/content/ssrf-guard.ts:117-129 blocks only a subset of IPv4 non-public ranges.
  • apps/web/src/lib/server/domains/settings/identity-providers.service.ts:282-307 uses checkUrlSafety for OIDC URLs and reports “valid https:// URL” even though http: passes the scheme check.
  • apps/web/src/lib/server/events/handlers/webhook.ts:30-47 defines a separate incomplete private-IP regex list.
  • apps/web/src/lib/server/events/handlers/webhook.ts:111-116 validates the resolved IP, but - apps/web/src/lib/server/events/handlers/webhook.ts:146-152 fetches the original URL, leaving a DNS rebinding window.

Impact

Sensitive server-side fetches can be routed to non-HTTPS endpoints or non-public network addresses that are not covered by the current blocklists. Outbound webhooks also rely on a validation/fetch split instead of connecting to the validated IP.

Recommended fix

Create one centralized SSRF policy and use it across OIDC, unfurling, outbound webhooks, and integration callbacks. Sensitive endpoints such as OIDC discovery, token, userinfo, and JWKS should require HTTPS. The guard should block all non-global IP ranges, including documentation, benchmarking, multicast, reserved, link-local, loopback, private, carrier-grade NAT, and IPv4-mapped IPv6 forms. Fetches should connect to the pinned validated IP and should not follow redirects to unvalidated hosts.

Acceptance criteria

  • OIDC provider URLs require https://.
  • All server-side URL fetchers use the same SSRF guard or an explicit policy wrapper.
  • The guard blocks all non-global IPv4 and IPv6 ranges.
  • Outbound webhooks connect to a validated pinned IP or use an equivalent TOCTOU-safe fetch path.
  • Tests cover 127.0.0.1, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 100.64.0.0/10, 169.254.169.254, 192.0.0.0/24, 198.18.0.0/15, multicast, reserved ranges, IPv6 loopback, IPv6 link-local, IPv6 ULA, IPv6 multicast, and IPv4-mapped IPv6.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions