{"record":{"id":"8441de1b846c043d","repo":"quarkusio/quarkus","slug":"control-character-in-cookie-value","errorCode":null,"errorMessage":"control character in cookie value","messagePattern":"control character in cookie value","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/headers/ServerCookie.java","lineNumber":236,"sourceCode":"\n    public static boolean alreadyQuoted(String value) {\n        if (value == null || value.length() == 0)\n            return false;\n        return (value.charAt(0) == '\\\"' && value.charAt(value.length() - 1) == '\\\"');\n    }\n\n    /**\n     * Quotes values using rules that vary depending on Cookie version.\n     *\n     * @param version cookie version\n     * @param buf buffer\n     * @param value value\n     */\n    public static void maybeQuote2(int version, StringBuffer buf, String value) {\n        if (value == null || value.length() == 0) {\n            buf.append(\"\\\"\\\"\");\n        } else if (containsCTL(value, version))\n            throw new IllegalArgumentException(\"control character in cookie value\");\n        else if (alreadyQuoted(value)) {\n            buf.append('\"');\n            buf.append(escapeDoubleQuotes(value, 1, value.length() - 1));\n            buf.append('\"');\n        } else if (version == 0 && !isToken(value)) {\n            buf.append('\"');\n            buf.append(escapeDoubleQuotes(value, 0, value.length()));\n            buf.append('\"');\n        } else if (version == 1 && !isToken2(value)) {\n            buf.append('\"');\n            buf.append(escapeDoubleQuotes(value, 0, value.length()));\n            buf.append('\"');\n        } else {\n            buf.append(value);\n        }\n    }\n\n    /**","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/headers/ServerCookie.java#L218-L254","documentation":"ServerCookie.maybeQuote2 appends a cookie value to a Set-Cookie header, quoting it when required. If the value contains control characters (CTL chars per the cookie spec, checked by containsCTL), it refuses to emit a malformed cookie and throws IllegalArgumentException instead of silently producing an invalid header.","triggerScenarios":"Setting a cookie whose value contains control characters (e.g. \\n, \\r, \\t, or chars < 0x20 / 0x7F), via NewCookie with such a value serialized through ServerCookie, or appending a raw user-input value into a cookie.","commonSituations":"Echoing unsanitized user input into a cookie value; log fragments or multi-line strings stored in cookies; values copied from headers or JSON containing newlines; header-injection防御 rejecting the value.","solutions":["Sanitize the cookie value: strip or replace control characters before setting it (e.g. value.replaceAll(\"[\\\\x00-\\\\x1F\\\\x7F]\", \"\")).","URL-encode (URLEncoder.encode / Base64) arbitrary payloads before storing them in cookies and decode on read.","Reduce what you store in the cookie — keep an opaque ID and keep the data server-side.","Catch IllegalArgumentException to reject the value and return a 400-style error instead of crashing."],"exampleFix":"// before\nNewCookie c = new NewCookie(\"session\", userInput); // userInput may contain \\n\n// after\nString safe = userInput == null ? \"\" : userInput.replaceAll(\"[\\\\x00-\\\\x1F\\\\x7F]\", \"\");\nNewCookie c = new NewCookie(\"session\", URLEncoder.encode(safe, StandardCharsets.UTF_8));","handlingStrategy":"validation","validationCode":"static String sanitizeCookieValue(String v) {\n    if (v == null) return \"\";\n    return v.replaceAll(\"[\\\\x00-\\\\x1F\\\\x7F]\", \"\");\n}\n// call: NewCookie c = new NewCookie(\"name\", sanitizeCookieValue(userInput));","typeGuard":"static boolean isSafeCookieValue(String v) {\n    return v != null && v.chars().noneMatch(c -> c < 0x20 || c == 0x7F);\n}","tryCatchPattern":"try {\n    ServerCookie.maybeQuote2(0, buf, value);\n} catch (IllegalArgumentException e) {\n    throw new BadRequestException(\"Illegal cookie value\");\n}","preventionTips":["URL-encode or Base64-encode arbitrary data before storing it in cookies.","Never copy raw user input or header fragments into cookie values.","Keep cookie values short, opaque identifiers where possible.","Reject control characters at input-validation time, not serialization time."],"tags":["http","cookie","validation","header-injection"],"backgroundTag":"invalid-cookie-value","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}