{"record":{"id":"fc2becc8936c6a38","repo":"eclipse-vertx/vert.x","slug":"a-header-value-contains-a-prohibited-character-12-fc2bec","errorCode":null,"errorMessage":"a header value contains a prohibited character '127': <seq>","messagePattern":"a header value contains a prohibited character '127': <seq>","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/http/impl/HttpUtils.java","lineNumber":732,"sourceCode":"      // 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) {\n        // Check the CRLF (HT | SP) pattern\n        switch (ch) {\n          case '\\r':\n            return CR_STATE;\n          case '\\n':\n            return LF_STATE;\n        }\n        return NO_CR_LF_STATE;\n      }\n    }\n    if (state != NO_CR_LF_STATE) {\n      // this is a rare scenario","sourceCodeStart":714,"sourceCodeEnd":750,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/http/impl/HttpUtils.java#L714-L750","documentation":"Inside validateValueChar, the per-character state machine for header values rejects DEL (0x7F) outright with IllegalArgumentException. This is the fine-grained path reached after a non-printable char triggers deeper validation; it guarantees no prohibited character ends up on the wire.","triggerScenarios":"Setting an HTTP header value that contains U+007F, validated by the state machine in validateValueChar (often entered via validateSequenceHeaderValue after a control char is seen).","commonSituations":"Header values assembled from binary or escaped data where a literal DEL survives; fuzzed or adversarial input passed into outgoing headers.","solutions":["Reject or sanitize values containing 0x7F before calling headers.set/add","Validate inputs at the boundary (decode/sanitize once) rather than at each header write","Encode opaque/binary data (Base64) instead of passing raw chars"],"exampleFix":"// before\nString v = new String(bytes, StandardCharsets.US_ASCII);\nrequest.putHeader(\"X-Data\", v);\n// after\nString v = Base64.getEncoder().encodeToString(bytes);\nrequest.putHeader(\"X-Data\", v);","handlingStrategy":"validation","validationCode":"boolean hasProhibitedChar(CharSequence v) {\n  for (int i = 0; i < v.length(); i++) {\n    char c = v.charAt(i);\n    if (c == 0x7F || (c < 0x20 && c != 0x09)) return true;\n  }\n  return false;\n}\nif (hasProhibitedChar(value)) value = sanitize(value);","typeGuard":null,"tryCatchPattern":"try {\n  request.putHeader(name, value);\n} catch (IllegalArgumentException e) {\n  request.putHeader(name, value.replaceAll(\"[\\\\u0000-\\\\u001F\\\\u007F]\", \"\"));\n}","preventionTips":["Sanitize once at the input boundary rather than at every header write","Use Base64 for opaque or binary header content","Fuzz-test outgoing header construction with control characters"],"tags":["http","headers","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-14T05:17:10.506Z"}