# `forwarded` — `X-Forwarded-Host` trust enforcement _(no submodules)_ ## Purpose Implements CIDR-based trust enforcement for the optional `X-Forwarded-Host` header. Edge proxies (CDN, load balancer, reverse proxy) rewrite the inbound `Host` to their internal hostname and stash the public host on `X-Forwarded-Host`. The resolver may honour that header, but ONLY when (a) the operator opted in via `trustForwardedHost: true` and (b) the upstream IP belongs to a trusted-proxy CIDR — otherwise a malicious client could spoof its tenant by sending `X-Forwarded-Host: victim.api.example.com` directly to the origin. This module owns the parser (`parseCidr`, `parseIp`) and the matcher (`cidrMatches`, `isTrustedProxy`) used by the resolver hot-path. ## Features - IPv4 and IPv6 support (including `::` shorthand and zone-id stripping). - Byte-array comparison with bit-aware prefix masking — no string manipulation in the hot-path. - Family-disjoint match — an IPv6 CIDR never matches an IPv4 address. - `parseCidr` returns `null` on malformed input so the caller (options parser) surfaces a stable `INVALID_OPTIONS` error rather than silently widening the trust set. ## Usage: Basic ```ts import { isTrustedProxy, parseCidr, } from "@suaveplan/api-tenant-resolver-subdomain/forwarded"; const cidrs = ["10.0.0.0/8", "2001:db8::/32"] .map((c) => parseCidr(c)!) .filter((c) => c !== null); isTrustedProxy("10.4.7.2", cidrs); // → true isTrustedProxy("8.8.8.8", cidrs); // → false ``` ## Usage: Advanced ```ts import { cidrMatches, parseCidr, parseIp, } from "@suaveplan/api-tenant-resolver-subdomain/forwarded"; const cidr = parseCidr("172.16.0.0/12"); const ip = parseIp("172.16.5.99"); if (cidr !== null && ip !== null && cidrMatches(ip, cidr)) { // ...trusted... } ``` ## API Reference - `ParsedCidr` — `{ bytes: Uint8Array; prefix: number; family: 4 | 6 }`. - `parseCidr(input: string): ParsedCidr | null`. - `parseIp(addr: string): { bytes: Uint8Array; family: 4 | 6 } | null`. - `cidrMatches(ip, cidr): boolean`. - `isTrustedProxy(remoteAddress, cidrs): boolean`. ## Implementation Notes IPv6 parsing handles the canonical `::` double-colon expansion, zone-id suffixes (`%eth0` is stripped — never meaningful for trust checks), and rejects > 8 groups or non-hex content. Prefix matching extracts the full-byte run with a byte-equality loop, then applies a high-bit mask to the trailing partial byte; `prefix === 0` is the "match everything in this family" case and is handled implicitly (loop runs zero times, tail short-circuit returns `true`). The module is dependency-free — no `node:net`, no `ipaddr.js`. This keeps the package universal and the CIDR parsing observable in tests without runtime injection.