{"record":{"id":"c32a8c0e7b8608ce","repo":"OpenNHP/opennhp","slug":"invalid-ip-address-s-c32a8c","errorCode":null,"errorMessage":"invalid IP address: %s","messagePattern":"invalid IP address: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nhp/utils/iputils.go","lineNumber":21,"sourceCode":"import (\n\t\"fmt\"\n\t\"net\"\n)\n\n// CIDR mask constants for IP address handling\nconst (\n\tIPv4SingleHost    = \"/32\"  // Single IPv4 host\n\tIPv4AdjacentRange = \"/25\"  // 128 IPv4 addresses\n\tIPv6SingleHost    = \"/128\" // Single IPv6 host\n\tIPv6AdjacentRange = \"/121\" // 128 IPv6 addresses (equivalent to IPv4 /25)\n)\n\n// DetectIPType parses an IP address string and returns whether it's IPv4 or IPv6.\n// Returns an error if the IP address is invalid.\nfunc DetectIPType(ipStr string) (IPTYPE, error) {\n\tip := net.ParseIP(ipStr)\n\tif ip == nil {\n\t\treturn 0, fmt.Errorf(\"invalid IP address: %s\", ipStr)\n\t}\n\tif ip.To4() != nil {\n\t\treturn IPV4, nil\n\t}\n\treturn IPV6, nil\n}\n\n// IsIPv6 returns true if the string is a valid IPv6 address.\n// Note: IPv4-mapped IPv6 addresses (::ffff:x.x.x.x) return false because\n// Go's net.IP.To4() returns a non-nil value for these addresses.\nfunc IsIPv6(ipStr string) bool {\n\tip := net.ParseIP(ipStr)\n\treturn ip != nil && ip.To4() == nil\n}\n\n// IsIPv4 returns true if the string is a valid IPv4 address.\nfunc IsIPv4(ipStr string) bool {\n\tip := net.ParseIP(ipStr)","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/nhp/utils/iputils.go#L3-L39","documentation":"DetectIPType in nhp/utils/iputils.go parses an IP string with net.ParseIP to classify it as IPv4 or IPv6. If parsing fails (nil), it returns this error instead of a type. It is a strict input-validation guard used by access-control handlers.","triggerScenarios":"Calling DetectIPType with a non-IP string: hostname ('example.com'), empty string, malformed address ('1.2.3', '300.1.1.1'), CIDR notation ('10.0.0.0/8'), or an address with port ('10.0.0.1:8080').","commonSituations":"Extracting client IPs from headers and including port or bracket syntax ('[::1]:8080'); config fields holding DNS names; log-parsing pipelines feeding raw tokens in.","solutions":["Strip port and CIDR suffixes before calling (net.SplitHostPort, strings.Cut on '/')","Resolve hostnames with net.LookupHost if names are expected","Validate with net.ParseIP at the config-load boundary and fail fast with a field name in the message","Trim whitespace"],"exampleFix":"// before\nipType, err := DetectIPType(\"10.0.0.1:8080\")\n// after\nhost, _, _ := net.SplitHostPort(\"10.0.0.1:8080\")\nipType, err := DetectIPType(host)","handlingStrategy":"validation","validationCode":"func normalizeIP(raw string) (string, error) {\n  s := strings.TrimSpace(raw)\n  if h, _, err := net.SplitHostPort(s); err == nil { s = h }\n  if i, _, err := net.ParseCIDR(s); err == nil { s = i.String() }\n  if net.ParseIP(s) == nil { return \"\", fmt.Errorf(\"not an IP: %q\", raw) }\n  return s, nil\n}","typeGuard":null,"tryCatchPattern":"ipType, err := DetectIPType(s); if err != nil { return fmt.Errorf(\"classify ip %q: %w\", s, err) }","preventionTips":["Sanitize header-extracted IPs (strip ports/brackets) before classification","Reject hostnames upstream or resolve them explicitly","Trim whitespace on all inbound address strings"],"tags":["ip-parsing","validation","networking"],"backgroundTag":"invalid-argument-format","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}