Skip to main content
All Docs
FeaturesMaking Tax DigitalUpdated March 11, 2026

Security: SSRF Prevention (SEC-10)

Security: SSRF Prevention (SEC-10)

Release: v1.0.408
OWASP Category: Server-Side Request Forgery (SSRF)
Affected file: src/lib/hmrc/client.ts

Background

The platform makes server-side HTTP requests to two external services:

  • HMRC API — for OAuth token exchange, quarterly submissions, annual summaries, and final declarations.
  • TrueLayer — for bank feed connectivity and redirect URI handling.

Base URLs for both services are sourced from environment variables, which is correct practice. However, prior to this release there was no runtime guard to verify that those URLs — or any URL derived from them — could not resolve to internal network addresses. This created a theoretical Server-Side Request Forgery (SSRF) risk: if an environment variable were misconfigured, or if a future code path introduced user-supplied URL fragments, the application server could be directed to make requests against internal infrastructure.

What Changed

A validateOutboundUrl() helper function has been added to src/lib/hmrc/client.ts and is invoked before every outbound fetch call.

Blocked address ranges

RangeDescription
127.0.0.0/8IPv4 loopback (localhost)
10.0.0.0/8RFC 1918 private range
172.16.0.0/12RFC 1918 private range
192.168.0.0/16RFC 1918 private range
169.254.0.0/16Link-local / instance metadata (e.g. 169.254.169.254)
::1IPv6 loopback
fc00::/7IPv6 unique local

If a URL resolves to any blocked range the function throws an error and the fetch is never attempted.

Where the guard is applied

  • HMRC API base URL (HMRC_API_BASE_URL)
  • TrueLayer API base URL (TRUELAYER_API_BASE_URL)
  • TrueLayer redirect URI (TRUELAYER_REDIRECT_URI)
  • Any future webhook delivery endpoints should also pass through validateOutboundUrl() before use.

Defence-in-Depth Rationale

Even though environment variables are set by trusted operators, runtime validation provides an additional layer of protection:

  1. Misconfiguration detection — A typo or incorrect value in an environment variable is caught immediately at request time with a clear error, rather than silently proxying to an unintended host.
  2. Future code safety — As new HMRC or third-party API integrations are added, applying validateOutboundUrl() consistently enforces a safe-by-default pattern across the codebase.
  3. Webhook endpoints — Any future feature that delivers webhook payloads to landlord-supplied URLs must pass those URLs through the same helper to prevent tenants from using the platform as an SSRF proxy.

Developer Guidance

When adding any new server-side fetch call, always validate the target URL first:

import { validateOutboundUrl } from '@/lib/hmrc/client';

// Throws if the URL resolves to a private/internal address
validateOutboundUrl(targetUrl);

const response = await fetch(targetUrl, { ... });

This applies to:

  • URLs from environment variables
  • URLs constructed from database-stored values
  • URLs provided directly or indirectly by end users (e.g. webhook callback URLs)

References