RedScore.ai

Fixes

Public Exposure · Updated 2026-05-02

Information Leakage Headers

Strips internal IPs (RFC 1918) and internal hostnames from response headers. Each finding deducts 15 of 30 pts; both = fail.

Reverse proxies, load balancers, and backend frameworks often add diagnostic information to response headers that is useful internally but dangerous to publish. Internal IPs in the RFC 1918 ranges (10.x, 172.16-31.x, 192.168.x), internal hostnames (lb-01, backend-prod-08, cache-iad7), and verbose proxy chains in the Via header all give an attacker a free map of your internal topology. This check scans every response header on every primary host and deducts points for each kind of leak found.

How the check works

Per primary host, every response header value is scanned for two patterns:

  • Internal IP: any value matching RFC 1918 ranges. Reason: internal_ip_in_headers. Deduction: 15 of 30 per-host points.
  • Internal hostname: values matching internal-hostname patterns (suffixes like .internal, .corp, .local; prefixes like backend-, lb-, cache-, internal-). Reason: internal_hostname_in_headers. Deduction: 15 of 30.
  • Verbose Via chain: a Via header with two or more comma-separated entries that also matches an internal-hostname or RFC 1918 pattern. Counts as a hostname signal.

Both kinds present: 30 deduction (capped), score 0.0 (fail). One kind: 15 deduction, score 0.5 (warn). Neither: 1.0 (pass). Per-host scores are weighted (apex highest) and averaged. Verdict thresholds: pass at 0.9 and above, warn at 0.45 and above, fail below.

How the verdict maps to evidence

  • Pass: no internal IPs or internal hostnames in any response header on any primary host.
  • Warn: one kind of leak on at least one host, or mixed coverage that drags the average between 0.45 and 0.9.
  • Fail: both kinds of leak on the same host, or several hosts each contributing leaks.

Evidence shows host_rows with each finding's header name, the kind of leak (internal_ip / internal_hostname / verbose_proxy_chain), and a value snippet so you can see exactly what is being exposed.

Special states

  • Degraded: probe data unavailable. Fix Web Assessability first.

Common offending headers

These are the most common sources of leaked information. The check picks them up by content, not by name; any header carrying RFC 1918 IPs or internal hostnames will trigger.

  • X-Backend-Server: backend-prod-08.internal.corp.tld
  • X-Upstream / X-Upstream-Server: 10.0.5.42:8080
  • X-Real-IP, X-Forwarded-For, X-Forwarded-Host: when accidentally returned in responses (these belong on requests, not responses).
  • Via: 1.1 lb-01.internal, 1.1 cache-iad7-12345.internal (verbose proxy chain).
  • X-Served-By: cache-iad7-12345-IAD
  • X-Cache-Hits: with internal hop identifiers
  • X-Pod-Name, X-Container-Id: Kubernetes-style debug headers leaking into responses
  • X-Origin-Server, X-Backend-Pool: load-balancer debug headers

Fix: strip diagnostic headers at the edge

The right place to strip these is the layer closest to the public internet (your CDN, reverse proxy, or front-end load balancer). Headers carrying internal topology should never make it past that boundary.

nginx (reverse proxy)

Strip common upstream-leak headers

# In your server { } block (or http { } for global):
proxy_hide_header X-Backend-Server;
proxy_hide_header X-Upstream;
proxy_hide_header X-Upstream-Server;
proxy_hide_header X-Served-By;
proxy_hide_header X-Cache-Hits;
proxy_hide_header X-Pod-Name;
proxy_hide_header X-Container-Id;
proxy_hide_header X-Origin-Server;
proxy_hide_header X-Backend-Pool;

# Reduce Via verbosity at this hop:
proxy_set_header Via "";

Apache (mod_proxy / mod_headers)

Strip leak headers in front-of-app Apache

Header unset X-Backend-Server
Header unset X-Upstream
Header unset X-Upstream-Server
Header unset X-Served-By
Header unset X-Cache-Hits
Header unset X-Pod-Name
Header unset X-Container-Id
Header unset X-Origin-Server
Header unset X-Backend-Pool

# Optional: control Via header
ProxyVia Off

HAProxy

Drop diagnostic headers in frontend

frontend public
    bind *:443 ssl crt /etc/ssl/yourdomain.pem
    http-response del-header X-Backend-Server
    http-response del-header X-Upstream
    http-response del-header X-Pod-Name
    http-response del-header X-Container-Id
    http-response del-header X-Served-By

Cloudflare (Transform Rules)

Modify Response Header → Remove

Add a Modify Response Header rule per leaky header:
  Action: Remove
  Header name: X-Backend-Server

Repeat for X-Upstream, X-Pod-Name, X-Container-Id, X-Served-By, etc.

AWS CloudFront (Response Headers Policy)

Override headers to empty

In a Response Headers Policy, Custom Headers section:
  Header: X-Backend-Server,  Value: (empty),  Override: Yes
  Header: X-Upstream,         Value: (empty),  Override: Yes
  Header: X-Pod-Name,         Value: (empty),  Override: Yes

Or use a CloudFront Function on viewer-response to delete the headers.

Source: stop the backend from sending them

Stripping at the edge is the catch-all, but the cleaner fix is to stop the backend setting the headers in the first place. Audit:

  • Reverse proxy modules: nginx upstream blocks can be configured to NOT pass diagnostic upstream headers downstream.
  • Application middleware: some Express, Rails, and ASP.NET middlewares add request-id and pod-name headers "helpfully". Disable in production.
  • Kubernetes ingress controllers: nginx-ingress and Traefik can add X-Pod-Name and similar; configure them to suppress.
  • Service mesh sidecars: Envoy/Istio can add tracing headers that leak service names. Configure outbound filter to strip on egress to public.

Verify the fix

  • curl -sI https://yourdomain.tld and read every header. Look for any value matching RFC 1918 (10.x, 172.16-31.x, 192.168.x) or internal-looking hostnames.
  • curl -s -I -X OPTIONS https://yourdomain.tld and curl -sI https://yourdomain.tld/some-known-bad-path. Different code paths sometimes set different headers.
  • Run the test from outside your network. Internal IP allow-lists may make leaks invisible to internal probing.
  • Re-run the RedScore lookup. Pass requires no RFC 1918 IPs or internal hostnames in any response header on any primary host.

Common pitfalls

  • Stripping at one layer, leaking at another. CDN strips X-Backend-Server but origin (reachable directly via Origin IP Exposure) still serves it. Strip at every layer between the app and the public internet.
  • Different header per code path. The default response from the apex may be clean while error pages, OPTIONS responses, or redirects from app routes still leak. The check probes more than just the home page; audit error paths too.
  • X-Forwarded-* headers in responses. These belong on REQUESTS to the origin, not on RESPONSES. Some misconfigured apps echo them back; strip them outbound.
  • Via header verbose by default. Many proxy stacks add verbose Via entries automatically. Configure ProxyVia Off (Apache) or proxy_set_header Via "" (nginx) to suppress.
  • Internal IPs in cookies or links. The check focuses on response headers; internal IPs in cookie values, Set-Cookie domain attributes, or HTML links also leak the same information and are caught by Response Content Leakage.
  • K8s pod identifiers re-added by the ingress controller. After removing X-Pod-Name from the app config, the ingress controller may re-add it. Audit the ingress config too.

What to do next

See how these recommendations apply to your site's current scan results.

Scan domain