quarkusio/quarkus · error · IllegalArgumentException
control character in cookie value
Error message
control character in cookie value
What it means
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.
Source
Thrown at independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/headers/ServerCookie.java:236
public static boolean alreadyQuoted(String value) {
if (value == null || value.length() == 0)
return false;
return (value.charAt(0) == '\"' && value.charAt(value.length() - 1) == '\"');
}
/**
* Quotes values using rules that vary depending on Cookie version.
*
* @param version cookie version
* @param buf buffer
* @param value value
*/
public static void maybeQuote2(int version, StringBuffer buf, String value) {
if (value == null || value.length() == 0) {
buf.append("\"\"");
} else if (containsCTL(value, version))
throw new IllegalArgumentException("control character in cookie value");
else if (alreadyQuoted(value)) {
buf.append('"');
buf.append(escapeDoubleQuotes(value, 1, value.length() - 1));
buf.append('"');
} else if (version == 0 && !isToken(value)) {
buf.append('"');
buf.append(escapeDoubleQuotes(value, 0, value.length()));
buf.append('"');
} else if (version == 1 && !isToken2(value)) {
buf.append('"');
buf.append(escapeDoubleQuotes(value, 0, value.length()));
buf.append('"');
} else {
buf.append(value);
}
}
/**View on GitHub (pinned to e1c734241f)
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.
Example fix
// before
NewCookie c = new NewCookie("session", userInput); // userInput may contain \n
// after
String safe = userInput == null ? "" : userInput.replaceAll("[\\x00-\\x1F\\x7F]", "");
NewCookie c = new NewCookie("session", URLEncoder.encode(safe, StandardCharsets.UTF_8)); Defensive patterns
Strategy: validation
Validate before calling
static String sanitizeCookieValue(String v) {
if (v == null) return "";
return v.replaceAll("[\\x00-\\x1F\\x7F]", "");
}
// call: NewCookie c = new NewCookie("name", sanitizeCookieValue(userInput)); Type guard
static boolean isSafeCookieValue(String v) {
return v != null && v.chars().noneMatch(c -> c < 0x20 || c == 0x7F);
} Try / catch
try {
ServerCookie.maybeQuote2(0, buf, value);
} catch (IllegalArgumentException e) {
throw new BadRequestException("Illegal cookie value");
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/8441de1b846c043d.
Report an issue: GitHub.