{"record":{"id":"b0845b51eaf28c08","repo":"nats-io/nats-server","slug":"unknown-proxy-protocol-command-0x-02x","errorCode":null,"errorMessage":"unknown PROXY protocol command: 0x%02x","messagePattern":"unknown PROXY protocol command: 0x%02x","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/client_proxyproto.go","lineNumber":350,"sourceCode":"\n\t// Parse address length (big-endian uint16)\n\taddrLen := binary.BigEndian.Uint16(header[2:4])\n\n\t// Handle LOCAL command (health check)\n\tif command == proxyProtoCmdLocal {\n\t\t// For LOCAL, we should skip the address data if any\n\t\tif addrLen > 0 {\n\t\t\t// Discard the address data\n\t\t\tif _, err := io.CopyN(io.Discard, conn, int64(addrLen)); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to discard LOCAL command address data: %w\", err)\n\t\t\t}\n\t\t}\n\t\treturn nil, nil // nil addr indicates LOCAL command\n\t}\n\n\t// Handle PROXY command\n\tif command != proxyProtoCmdProxy {\n\t\treturn nil, fmt.Errorf(\"unknown PROXY protocol command: 0x%02x\", command)\n\t}\n\n\t// Validate protocol (we only support STREAM/TCP)\n\tif protocol != proxyProtoProtoStream {\n\t\treturn nil, fmt.Errorf(\"%w: only STREAM protocol supported\", errProxyProtoUnsupported)\n\t}\n\n\t// Parse address data based on family\n\tvar addr *proxyProtoAddr\n\tvar err error\n\tswitch family {\n\tcase proxyProtoFamilyInet:\n\t\taddr, err = parseIPv4Addr(conn, addrLen)\n\tcase proxyProtoFamilyInet6:\n\t\taddr, err = parseIPv6Addr(conn, addrLen)\n\tcase proxyProtoFamilyUnspec:\n\t\t// UNSPEC family with PROXY command is valid but rare\n\t\t// Just skip the address data","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/client_proxyproto.go#L332-L368","documentation":"The PROXY protocol v2 spec defines only two commands: LOCAL (0x0) and PROXY (0x1). This error is raised when the command nibble of the ver/cmd byte holds any other value, meaning the sender produced a header the library does not recognize. It is returned as-is (not wrapped in a sentinel), so callers must string-match rather than errors.Is.","triggerScenarios":"A peer sends a valid v2 signature but the ver/cmd low nibble is >= 0x2, e.g. command bits 0x2-0xF from a buggy sender, bit-flipped corruption, or a custom/nonstandard sender.","commonSituations":"Firmware bugs in proxies emitting reserved command values; memory/bit corruption on the wire; handcrafted clients testing the parser; protocol extensions the server has not implemented.","solutions":["Fix or update the upstream sender to emit only LOCAL (0x0) or PROXY (0x1) commands","Dump the ver/cmd byte to identify which value is being sent","Check the proxy vendor's documentation for nonstandard command extensions","If the command is legitimate per a newer spec revision, patch parseProxyProtoV2Header to handle it"],"exampleFix":"// before (sender)\nverCmd := 0x22 // command 0x2 unsupported\n// after\nverCmd := 0x21 // command PROXY (0x1)","handlingStrategy":"try-catch","validationCode":"// Only 0x0 (LOCAL) and 0x1 (PROXY) are valid command nibbles\nif c := hdr[12]&0x0F; c > 0x1 {\n    return fmt.Errorf(\"invalid PROXY v2 command 0x%x\", c)\n}","typeGuard":"func isKnownProxyCmd(b byte) bool { c := b&0x0F; return c == 0x0 || c == 0x1 }","tryCatchPattern":"addr, err := readProxyProtoHeader(conn)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"unknown PROXY protocol command\") {\n        // log ver/cmd byte, close connection — sender is non-conformant\n        conn.Close()\n        return\n    }\n    return err\n}","preventionTips":["Audit senders to emit only LOCAL (0x0) or PROXY (0x1) command nibbles","Fuzz-test the parser with random command values in staging","Log the raw ver/cmd byte when this fires to identify the offending sender","Check vendor docs for nonstandard command extensions before enabling"],"tags":["proxy-protocol","protocol-violation","network"],"backgroundTag":"proxy-protocol-unknown-command","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}