abhigyanpatwari/GitNexus · warning
[gitnexus serve] Bound to ${boundHost} with ${TRUST_PROXY_EN
Error message
[gitnexus serve] Bound to ${boundHost} with ${TRUST_PROXY_ENV} unset, so 'trust proxy' is '${DEFAULT_TRUST_PROXY}'. A load balancer outside those ranges is not trusted, so req.ip is the balancer on every request and the per-IP rate limit becomes one shared limit across all callers. Set ${TRUST_PROXY_ENV} to the number of proxies you control. What it means
warnIfRateLimitKeysCollapse fires when serve binds a non-loopback host and GITNEXUS_TRUST_PROXY is unset. The default 'trust proxy' value ('loopback, linklocal, uniquelocal') does not trust a load balancer outside those ranges, so req.ip resolves to the balancer's address on every request and the per-IP rate limit collapses into one shared limit across all callers — one abusive client can exhaust everyone's quota.
Source
Thrown at gitnexus/src/server/middleware.ts:382
* {@link resolveTrustProxy} cannot detect this — it sees the env value and not
* what the server bound. A non-loopback bind is the shape of a deployment behind
* a load balancer, and {@link DEFAULT_TRUST_PROXY} matches only loopback and the
* private ranges, so a cloud LB outside them is never trusted: `req.ip` is the
* LB on every request and the per-IP limit silently becomes one global limit.
*
* Silent when {@link TRUST_PROXY_ENV} is set — including to a value that then
* fails validation, which {@link resolveTrustProxy} has already warned about.
*
* @param boundHost - `createServer`'s `host`. A wildcard bind warns too: it
* accepts traffic on every interface, a load balancer included.
*/
export function warnIfRateLimitKeysCollapse(boundHost?: string): void {
if (process.env[TRUST_PROXY_ENV]?.trim()) return;
if (!boundHost) return;
// normalizeBoundHost returns undefined for a wildcard or unparseable host,
// neither of which is loopback — so both warn.
if (isLoopbackHostname(normalizeBoundHost(boundHost))) return;
logger.warn(
{ host: boundHost, trustProxy: DEFAULT_TRUST_PROXY },
`[gitnexus serve] Bound to ${boundHost} with ${TRUST_PROXY_ENV} unset, so 'trust proxy' is ` +
`'${DEFAULT_TRUST_PROXY}'. A load balancer outside those ranges is not trusted, so req.ip ` +
`is the balancer on every request and the per-IP rate limit becomes one shared limit across ` +
`all callers. Set ${TRUST_PROXY_ENV} to the number of proxies you control.`,
);
}
function rejectTrustProxy(value: string, reason: string): string {
logger.warn(
{ [TRUST_PROXY_ENV]: value },
`[gitnexus serve] Ignoring ${TRUST_PROXY_ENV}=${value} (${reason}); falling back to ` +
`'${DEFAULT_TRUST_PROXY}'.`,
);
return DEFAULT_TRUST_PROXY;
}
View on GitHub (pinned to aac7515d2a)
Solutions
- Set GITNEXUS_TRUST_PROXY to the number of proxies you control, e.g. GITNEXUS_TRUST_PROXY=1
- Confirm your proxy sets X-Forwarded-For correctly, otherwise trusting it accomplishes nothing
- If there is truly no proxy in front, the warning is a false alarm: prefer a loopback bind and it stays silent
Example fix
# before gitnexus serve --host 0.0.0.0 # behind an ALB: req.ip == balancer for everyone # after GITNEXUS_TRUST_PROXY=1 gitnexus serve --host 0.0.0.0 # req.ip == real client IP
Defensive patterns
Strategy: validation
Validate before calling
const trustProxy = process.env.GITNEXUS_TRUST_PROXY?.trim();
if (!trustProxy && boundHost && !isLoopbackHostname(boundHost)) {
// Behind a non-RFC1918 load balancer, per-IP rate limits collapse into
// one shared bucket — refuse to start until the hop count is set.
throw new Error('Set GITNEXUS_TRUST_PROXY=<proxy hop count> when serving behind a proxy');
} Prevention
- Set GITNEXUS_TRUST_PROXY to your proxy count in every proxied deployment
- Verify your proxy actually sets X-Forwarded-For
- Watch for sudden all-user 429s — the signature of collapsed rate-limit keys
When it happens
Trigger: gitnexus serve bound to a non-loopback (or wildcard) host behind a cloud load balancer or reverse proxy outside RFC1918/link-local ranges, with GITNEXUS_TRUST_PROXY unset: every request lands in a single rate-limit bucket keyed on the balancer IP.
Common situations: Deploying behind ALB/Cloudflare/nginx on a public subnet; the visible symptom is organization-wide 429 responses triggered by one heavy consumer — the classic Express trust-proxy collapse.
Related errors
- [gitnexus serve] Ignoring ${PUBLIC_ORIGIN_ENV}=${raw} — not
- [gitnexus serve] Ignoring ${TRUST_PROXY_ENV}=${value} (${rea
- ${name} must be a positive integer, got "${raw}"
- ${name} must be a positive integer <= ${max}, got "${raw}"
- ${name} must be a non-negative integer, got "${raw}"
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/7d0f369eb9ddccc8.
Report an issue: GitHub.