Ensuring Gov-Vendor-Public-IP is Always Sent to HMRC
Ensuring Gov-Vendor-Public-IP is Always Sent to HMRC
Release: v1.0.201 · Severity: MEDIUM · Area: HMRC Fraud Prevention Headers
Background
HMRC's Making Tax Digital (MTD) API enforces a set of fraud prevention headers on all inbound requests. These headers allow HMRC to detect and deter fraudulent submissions. For applications using the WEB_APP_VIA_SERVER connection method — which includes this platform — one of the mandatory headers is:
Gov-Vendor-Public-IP: <public IPv4 or IPv6 address of the server>
HMRC validates these headers and will return a 403 INVALID_FRAUD_PREVENTION_HEADERS error if any required header is missing or malformed.
The Problem
A depth audit of src/lib/hmrc/fraud-prevention-headers.ts (line 101) revealed that when the VENDOR_PUBLIC_IP environment variable was not configured, the code fell back to an empty string. As a result:
- The
Gov-Vendor-Public-IPheader was included in the request but contained no value — or was omitted entirely. - HMRC's fraud prevention validation would reject the request.
- The failure mode was silent: no startup warning or runtime error was raised to alert operators.
The Fix
The fallback behaviour has been corrected. The application now:
- Validates the
VENDOR_PUBLIC_IPenvironment variable at request time. - Raises a configuration error if the variable is absent or empty, rather than sending a non-compliant header.
- Includes a well-formed
Gov-Vendor-Public-IPheader in all HMRC API requests when the variable is correctly set.
Configuration
Ensure the following environment variable is set in your deployment environment:
| Variable | Description | Example |
|---|---|---|
VENDOR_PUBLIC_IP | The public-facing IP address of your application server, as seen by HMRC. | 203.0.113.42 |
Where to find your public IP
- Cloud providers (AWS, GCP, Azure): Use an Elastic IP, Static External IP, or equivalent. Do not use a private/internal IP — HMRC must be able to see this address.
- On-premise / VPS: Run
curl -s https://api.ipify.orgfrom the server to confirm the public IP. - Behind a NAT/proxy: Use the egress IP of the NAT gateway, not the instance's private IP.
Setting the variable
.env / .env.production
VENDOR_PUBLIC_IP=203.0.113.42
Docker / container environments
docker run -e VENDOR_PUBLIC_IP=203.0.113.42 ...
Kubernetes
env:
- name: VENDOR_PUBLIC_IP
value: "203.0.113.42"
Verifying Compliance
After deploying, you can confirm the header is being sent correctly by inspecting outbound requests in your application logs or by using HMRC's Test Fraud Prevention Headers API in the sandbox environment.
A compliant request will include a header such as:
Gov-Vendor-Public-IP: 203.0.113.42
An absent or empty header will result in HMRC returning:
{
"code": "INVALID_FRAUD_PREVENTION_HEADERS",
"message": "The request has invalid fraud prevention headers"
}
with HTTP status 403.