Skip to content

fix(webhooks): constrain subscription URLs against SSRF and add webhook unit tests (#280, #170) - #301

Open
ocakciomursel-pixel wants to merge 1 commit into
SourceXXL:mainfrom
ocakciomursel-pixel:fix/webhook-ssrf-and-unit-tests
Open

ocakciomursel-pixel wants to merge 1 commit into
SourceXXL:mainfrom
ocakciomursel-pixel:fix/webhook-ssrf-and-unit-tests

Conversation

@ocakciomursel-pixel

Copy link
Copy Markdown

Summary

Closes #280
Closes #170

This PR hardens the Webhook infrastructure against Server-Side Request Forgery (SSRF) across both subscription registration/update and outbound delivery (#280), and adds full unit test coverage for all services in src/infrastructure/webhooks/services/ (#170).


1. Webhook SSRF & Outbound Delivery Hardening (#280)

  • WebhookUrlValidatorService (src/infrastructure/webhooks/services/webhook-url-validator.service.ts):
    • Scheme allowlist: Enforces https: by default; permits http: only in NODE_ENV=development or when WEBHOOK_ALLOW_INSECURE_HTTP=true outside production. Rejects file:, gopher:, ftp:, data:, and URLs with embedded credentials.
    • Port allowlist: Permits standard webhook ports (443, plus 80 when http: is allowed) and optional custom ports via WEBHOOK_ALLOWED_PORTS.
    • Hostname & IP range blocking: Blocks reserved hostnames (localhost, *.localhost, *.local, *.internal, metadata.google.internal), obfuscated IPv4 encodings (short-form 127.1, integer 2130706433, hex 0x7f000001, octal 0177.0.0.1), and private/reserved IPv4 & IPv6 ranges (loopback 127.0.0.0/8, ::1/128, RFC 1918 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, link-local & cloud metadata 169.254.0.0/16 / 169.254.169.254, CGNAT 100.64.0.0/10, IPv4-mapped/translated IPv6 ::ffff:0:0/96, unique-local fc00::/7, link-local fe80::/10).
    • DNS resolution check: Resolves hostnames via dns.promises.lookup(..., { all: true, verbatim: true }) and rejects endpoints if any resolved A/AAAA record falls in a blocked range.
  • Registration & Update Validation (WebhookSubscriptionService):
    • Validates dto.url on both create() and update(), and avoids logging raw user-supplied URLs.
  • Delivery-Time Re-Resolution, Redirect Blocking & Rate Limiting (WebhookDeliveryService, WebhookController):
    • Re-validates and re-resolves subscription.url immediately before each delivery attempt and pins the resolved IP on the outbound http.Agent / https.Agent lookup callback to defeat DNS rebinding.
    • Disables redirect following (maxRedirects: 0) and treats 3xx responses as delivery failures rather than following redirects to internal endpoints.
    • Enforces per-subscription outbound rate limiting (subscription.rateLimitPerMinute sliding 60s window).
    • Truncates stored response bodies (max 512 chars) and scopes retryDeadLetter / getMetrics to the authenticated user.

2. Webhook Unit Test Suite (#170)

Added colocated unit specs under src/infrastructure/webhooks/services/ and wired src/infrastructure/webhooks into .github/workflows/build-check.yml:

  • webhook-url-validator.service.spec.ts
  • webhook-hmac.service.spec.ts
  • webhook-subscription.service.spec.ts
  • webhook-delivery.service.spec.ts
  • webhook-event.service.spec.ts
  • webhook-processor.service.spec.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant