{"record":{"id":"ebccbcbde82f1466","repo":"Netflix/zuul","slug":"invalid-header-field-char-int-value-charat-po","errorCode":null,"errorMessage":"Invalid header field: char ${(int) value.charAt(pos)} in string ${value} does not comply with RFC 7230","messagePattern":"Invalid header field: char (.+?) in string (.+?) does not comply with RFC 7230","errorType":"validation","errorClass":"ZuulException","httpStatus":null,"severity":"error","filePath":"zuul-core/src/main/java/com/netflix/zuul/message/Headers.java","lineNumber":785,"sourceCode":"     */\n    private static boolean isValid(@Nullable String value) {\n        if (value == null || findInvalid(value) == ABSENT) {\n            return true;\n        }\n        invalidHeaderCounter.increment();\n        return false;\n    }\n\n    /**\n     * Checks if the input value is compliant with our RFC 7230 based check\n     * Returns input value if valid, raises ZuulException otherwise\n     */\n    private static String validateField(@Nullable String value) {\n        if (value != null) {\n            int pos = findInvalid(value);\n            if (pos != ABSENT) {\n                invalidHeaderCounter.increment();\n                throw new ZuulException(\"Invalid header field: char \" + (int) value.charAt(pos) + \" in string \" + value\n                        + \" does not comply with RFC 7230\");\n            }\n        }\n        return value;\n    }\n\n    /**\n     * Validated the input value based on RFC 7230 but more lenient.\n     * Currently, only ASCII control characters are considered invalid.\n     *\n     * Returns the index of first invalid character. Returns {@link #ABSENT} if absent.\n     */\n    private static int findInvalid(String value) {\n        for (int i = 0; i < value.length(); i++) {\n            char c = value.charAt(i);\n            // ASCII non-control characters, per RFC 7230 but slightly more lenient\n            if (c < 31 || c == 127) {\n                return i;","sourceCodeStart":767,"sourceCodeEnd":803,"githubUrl":"https://github.com/Netflix/zuul/blob/14bf53c52dcf571894619ff65a674cbe2cce3ac6/zuul-core/src/main/java/com/netflix/zuul/message/Headers.java#L767-L803","documentation":"Zuul validates every HTTP header value against RFC 7230 field-content rules before storing it in a Headers object. If a value contains a forbidden character (e.g. CTL characters, bare newline/carriage-return outside obs-fold handling, or other non-visible ASCII), Headers increments an invalidHeaderCounter metric and throws this ZuulException. This is a security/robustness guard against header-injection and malformed header propagation.","triggerScenarios":"Calling any Headers add/set/put/constructor path (all route through validateField) with a header value containing a character rejected by findInvalid — commonly \\r, \\n, or non-ASCII/control characters — e.g. building a request header from untrusted user input or a downstream service echo.","commonSituations":"User-supplied input copied verbatim into a proxied header (X-Forwarded-*, custom tracing headers); log injection attempts with CRLF; legacy systems emitting Latin-1/UTF-8 bytes in header values; faulty upstream responses echoing header values with embedded newlines.","solutions":["Sanitize the header value before adding it: strip or percent-encode control/non-ASCII characters (only visible ASCII + SP/HT allowed per RFC 7230).","Replace line breaks and invalid characters, e.g. value.replaceAll(\"[\\\\r\\\\n\\\\t\\\\x00-\\\\x1f\\\\x7f]\", \"\") before headers.add(...).","Trace which header/value is invalid from the message (it includes the offending char code and full string) and fix the producer of that value.","If the value legitimately needs non-ASCII, encode it (e.g. RFC 5987/2047 encoding) rather than passing raw bytes.","For responses from origins, validate/normalize headers before copying them into the Zuul Headers object."],"exampleFix":"// before\nString traceId = request.getParameter(\"traceId\");\nheaders.add(\"X-Trace-Id\", traceId);\n// after\nString traceId = request.getParameter(\"traceId\").replaceAll(\"[^\\\\x20-\\\\x7E]\", \"\");\nheaders.add(\"X-Trace-Id\", traceId);","handlingStrategy":"validation","validationCode":"// validate/sanitize header values before adding to Zuul Headers\nprivate static final Pattern VALID_HEADER = Pattern.compile(\"^[\\\\x20-\\\\x7E]+$\");\nstatic String safeHeader(String value) {\n    if (value == null || !VALID_HEADER.matcher(value).matches()) {\n        throw new IllegalArgumentException(\"Invalid header value\");\n    }\n    return value;\n}\nheaders.add(\"X-Custom\", safeHeader(userInput));","typeGuard":"boolean isRfc7230Header(String value) {\n    return value != null && value.chars().allMatch(c -> c == '\\t' || (c >= 0x20 && c <= 0x7E));\n}","tryCatchPattern":"try {\n    headers.add(\"X-Trace-Id\", userInput);\n} catch (ZuulException e) {\n    if (e.getMessage().startsWith(\"Invalid header field\")) {\n        log.warn(\"Dropping invalid header value: {}\", e.getMessage());\n    }\n}","preventionTips":["Strip CR/LF and control characters from any user-supplied data before putting it in headers","Only allow visible ASCII (0x20-0x7E) plus HTAB in header values","Encode non-ASCII content (RFC 5987/2047) instead of passing raw bytes","Validate headers copied from untrusted origins before adding them to Zuul Headers","Watch the invalidHeaderCounter metric for spikes indicating injection attempts"],"tags":["http","headers","rfc7230","validation","header-injection"],"backgroundTag":"invalid-argument-format","analyzedSha":"14bf53c52dcf571894619ff65a674cbe2cce3ac6","analyzedAt":"2026-09-07T10:00:54.873Z","contentChangedAt":"2026-09-07T10:00:54.873Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}