{"record":{"id":"5cef1d1a6f0f7a64","repo":"caddyserver/caddy","slug":"parsing-cidr-expression-s-v-5cef1d","errorCode":null,"errorMessage":"parsing CIDR expression: '%s': %v","messagePattern":"parsing CIDR expression: '(.+?)': (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/reverseproxy/reverseproxy.go","lineNumber":324,"sourceCode":"\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"loading circuit breaker: %s\", err)\n\t\t}\n\t\th.CB = mod.(CircuitBreaker)\n\t}\n\tif h.DynamicUpstreamsRaw != nil {\n\t\tmod, err := ctx.LoadModule(h, \"DynamicUpstreamsRaw\")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"loading upstream source module: %v\", err)\n\t\t}\n\t\th.DynamicUpstreams = mod.(UpstreamSource)\n\t}\n\n\t// parse trusted proxy CIDRs ahead of time\n\tfor _, str := range h.TrustedProxies {\n\t\tif strings.Contains(str, \"/\") {\n\t\t\tipNet, err := netip.ParsePrefix(str)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"parsing CIDR expression: '%s': %v\", str, err)\n\t\t\t}\n\t\t\th.trustedProxies = append(h.trustedProxies, ipNet)\n\t\t} else {\n\t\t\tipAddr, err := netip.ParseAddr(str)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"invalid IP address: '%s': %v\", str, err)\n\t\t\t}\n\t\t\tipNew := netip.PrefixFrom(ipAddr, ipAddr.BitLen())\n\t\t\th.trustedProxies = append(h.trustedProxies, ipNew)\n\t\t}\n\t}\n\n\t// ensure any embedded headers handler module gets provisioned\n\t// (see https://caddy.community/t/set-cookie-manipulation-in-reverse-proxy/7666?u=matt\n\t// for what happens if we forget to provision it)\n\tif h.Headers != nil {\n\t\terr := h.Headers.Provision(ctx)\n\t\tif err != nil {","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/reverseproxy/reverseproxy.go#L306-L342","documentation":"Each entry in trusted_proxies is parsed at provision time: strings containing '/' go through netip.ParsePrefix (CIDR), everything else through netip.ParseAddr. A malformed CIDR (bad bits field, stray spaces, embedded hostname) or an invalid bare IP yields 'parsing CIDR expression: '%s': %v' or 'invalid IP address'. Note there is no hostname resolution — the value must already be an IP or CIDR literal.","triggerScenarios":"trusted_proxies 10.0.0.0/8 192.168.1.5 works; trusted_proxies proxy.internal (a hostname), 10.0.0.0/33 (invalid prefix length), 10.0.0.1/24 (host bits set — ParsePrefix rejects), or a value with whitespace/quotes from env-var interpolation fails.","commonSituations":"See trigger scenarios.","solutions":["Replace hostnames with concrete IPs or CIDRs (resolve once, or maintain the list manually): trusted_proxies 10.0.0.0/8 192.168.0.0/16.","For CIDRs, mask host bits and keep the prefix length valid (0–32 for v4, 0–128 for v6): use 10.0.0.0/24 not 10.0.0.1/24.","If the list comes from an env placeholder, print the rendered config (caddy adapt) and sanitize the injected value.","Use private_ranges only when full RFC1918+loopback trust is acceptable."],"exampleFix":"# before\nreverse_proxy localhost:8080 {\n    trusted_proxies proxy.internal 10.0.0.1/24\n}\n\n# after\nreverse_proxy localhost:8080 {\n    trusted_proxies 10.0.0.0/24 192.168.1.10\n}","handlingStrategy":"validation","validationCode":"import \"net/netip\"\n\nfunc validateTrustedProxies(entries []string) error {\n    for _, s := range entries {\n        if strings.Contains(s, \"/\") {\n            if _, err := netip.ParsePrefix(s); err != nil {\n                return fmt.Errorf(\"bad CIDR %q: %w\", s, err)\n            }\n            continue\n        }\n        if _, err := netip.ParseAddr(s); err != nil {\n            return fmt.Errorf(\"bad IP %q: %w\", s, err)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only IPs and CIDR literals are allowed — resolve hostnames before writing them into config.","Use masked CIDRs (10.0.0.0/24), never host-bit forms (10.0.0.1/24).","When injecting trusted_proxies from env vars, sanitize and caddy adapt the rendered config in CI."],"tags":["config","network","ip","validation","reverseproxy"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}