{"record":{"id":"bb418d408ac16ef3","repo":"eclipse-vertx/vert.x","slug":"a-header-value-must-not-end-with-r-or-n-seq","errorCode":null,"errorMessage":"a header value must not end with '\\r' or '\\n':<seq>","messagePattern":"a header value must not end with '\\\\r' or '\\\\n':<seq>","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/http/impl/HttpUtils.java","lineNumber":720,"sourceCode":"    }\n  }\n\n  private static final int HIGHEST_INVALID_VALUE_CHAR_MASK = ~0x1F;\n  private static final int NO_CR_LF_STATE = 0;\n  private static final int CR_STATE = 1;\n  private static final int LF_STATE = 2;\n\n  /**\n   * This method is taken as we need to validate the header value for the non-printable characters.\n   */\n  private static void validateSequenceHeaderValue(CharSequence seq, int index) {\n      // we already expect the very-first character to be non-printable\n      int state = validateValueChar(seq, NO_CR_LF_STATE, seq.charAt(index));\n      for (int i = index + 1; i < seq.length(); i++) {\n        state = validateValueChar(seq, state, seq.charAt(i));\n      }\n      if (state != NO_CR_LF_STATE) {\n        throw new IllegalArgumentException(\"a header value must not end with '\\\\r' or '\\\\n':\" + seq);\n      }\n  }\n\n  private static int validateValueChar(CharSequence seq, int state, char ch) {\n    /*\n     * State:\n     * 0: Previous character was neither CR nor LF\n     * 1: The previous character was CR\n     * 2: The previous character was LF\n     */\n    if (ch == 0x7F) {\n      throw new IllegalArgumentException(\"a header value contains a prohibited character '127': \" + seq);\n    }\n    if ((ch & HIGHEST_INVALID_VALUE_CHAR_MASK) == 0) {\n      // this is a rare scenario\n      validateNonPrintableCtrlChar(seq, ch);\n      // this can include LF and CR as they are non-printable characters\n      if (state == NO_CR_LF_STATE) {","sourceCodeStart":702,"sourceCodeEnd":738,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/http/impl/HttpUtils.java#L702-L738","documentation":"After scanning a header value, if the CR/LF state machine in validateSequenceHeaderValue does not end in the NO_CR_LF_STATE, the value terminates in a bare '\\r' or '\\n'. Such values allow HTTP response-splitting/request-smuggling, so Vert.x throws IllegalArgumentException.","triggerScenarios":"Setting an HTTP header whose value ends with '\\r' or '\\n' (or a CR-LF combination) — detected by the final state check after validateValueChar walks the whole sequence.","commonSituations":"Joining multi-line config or log text into a single header; appending line separators to header values by mistake; untrusted input containing trailing newline kept untrimmed.","solutions":["Trim trailing CR/LF characters from the value before setting the header","Join multi-line content with a single space or use a separator like \", \" instead of \\r\\n","Never pass untrusted, untrimmed input directly as a header value"],"exampleFix":"// before\nString v = multiLineDescription; // ends with \"\\n\"\nrequest.putHeader(\"X-Desc\", v);\n// after\nString v = multiLineDescription.replaceAll(\"[\\\\r\\\\n]+$\", \"\").replace(\"\\r\\n\", \" \");\nrequest.putHeader(\"X-Desc\", v);","handlingStrategy":"validation","validationCode":"String stripTrailingCrLf(String v) {\n  int end = v.length();\n  while (end > 0 && (v.charAt(end - 1) == '\\r' || v.charAt(end - 1) == '\\n')) end--;\n  return v.substring(0, end);\n}\n// apply before headers.set/add","typeGuard":null,"tryCatchPattern":"try {\n  request.putHeader(name, value);\n} catch (IllegalArgumentException e) {\n  request.putHeader(name, stripTrailingCrLf(value).replace(\"\\r\\n\", \" \"));\n}","preventionTips":["Trim trailing CR/LF from all header values, especially untrusted input","Replace internal line breaks with spaces when flattening multi-line text","Treat any header containing CR/LF as suspicious (request-smuggling defense)"],"tags":["http","headers","request-smuggling","validation"],"backgroundTag":"invalid-header-value","analyzedSha":"fb308bd8c3f12c79f4ae89bef67fadf6c80d036e","analyzedAt":"2026-09-06T11:37:12.241Z","contentChangedAt":"2026-09-06T11:37:12.241Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}