Safeguard
Security Guides•

What does Express's trust proxy setting do, and how do you set it safely?

Express trust proxy decides whether req.ip and req.protocol believe X-Forwarded headers. A wrong value lets clients fake their IP and dodge rate limits.

Safeguard Security Team
3 min read

The trust proxy setting tells Express which X-Forwarded headers to believe. The default is false, so req.ip comes from the socket. Behind a reverse proxy you set it to match your real proxy chain. Set it too loosely and any client can claim any IP address.

Why it matters

Behind a load balancer, the socket address is the balancer, so every user looks like one IP. Teams then turn trust proxy on to get the real address back. That address often feeds rate limiting, audit logs and allow lists. If a client can forge it, all three break.

The documented value types

ValueMeaning
false (default)App faces the client directly, IP comes from the socket
trueClient IP is the left most X-Forwarded-For entry
IP, subnet or listTrust those as proxies, take the nearest untrusted address
NumberTrust that many hops from the app
FunctionYour own trust logic

Express also ships named subnets: loopback, linklocal and uniquelocal.

The two warnings in the docs

First, when set to true, the last reverse proxy you trust must remove or overwrite X-Forwarded-For, X-Forwarded-Host and X-Forwarded-Proto. Otherwise the client can supply any value.

Second, with a hop count, make sure there are not multiple paths of different length to the app. If a client can reach the app by a shorter path, it may be fewer hops away than you configured and can then supply any value.

The guide's own advice is to understand your exact proxy setup, because the setting trusts values supplied in the request.

Steps to set it

  1. Draw the real path: client, CDN, load balancer, your app. Count the hops you control.
  2. Prefer a list of known proxy addresses or subnets over the plain true value.
  3. Make sure the outermost trusted proxy overwrites forwarded headers instead of appending client supplied ones.
  4. Test from outside. Send a request with a fake X-Forwarded-For and confirm the logged IP is not the fake one.
  5. Use the same trusted value in anything that reads the IP, such as your rate limiter.
// Only trust the proxy in your private network range
app.set('trust proxy', 'uniquelocal');

app.get('/whoami', (req, res) => {
  res.json({ ip: req.ip, ips: req.ips, protocol: req.protocol });
});

Other effects of turning it on

The guide lists three consequences. req.hostname derives from X-Forwarded-Host, which can be set by the client or the proxy. req.protocol reflects X-Forwarded-Proto, which could even be an invalid name. req.ip and req.ips come from the socket address and X-Forwarded-For, starting at the first untrusted address. If you build absolute links or redirects from req.hostname, validate them. See the open redirect post.

For limiters, read four silent ways a rate limiter permits everything.

Safeguard's policies and gates can enforce checks like this in review, and a free scan at gold.safeguard.sh/scan covers your dependency side.

Quick check

Should I just set trust proxy to true?

Only if the last proxy in front of your app strips and rewrites the forwarded headers. A specific address or subnet list is the safer habit.

Why is every request showing the same IP?

Likely trust proxy is still false, so Express reports the proxy's socket address. Set it to match your proxy chain.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.