Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Response Splitting')

ID

scala.cookie.scala_cookie_rule_httpresponsesplitting

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Cookie

Language

Scala

Description

When an HTTP request contains unexpected CR and LF characters, the server may respond with an output stream that is interpreted as two different HTTP responses (instead of one). An attacker can control the second response and mount attacks such as cross-site scripting and cache poisoning attacks.

Rationale

When an HTTP request contains unexpected CR and LF characters, the server may respond with an output stream that is interpreted as two different HTTP responses (instead of one). An attacker can control the second response and mount attacks such as cross-site scripting and cache poisoning attacks.

The following code illustrates a vulnerable pattern detected by this rule:

class ProfileServlet extends HttpServlet {
  @throws[ServletException]
  @throws[IOException]
  override protected def doGet(request: HttpServletRequest, response: HttpServletResponse): Unit = {
    val nickname = request.getParameter("nickname")
    val profile = new Cookie("profile", null)
    // VULNERABLE: Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Response Splitting')
    profile.setValue(nickname)
    profile.setHttpOnly(true)
    profile.setSecure(true)
    response.addCookie(profile)
  }

  @throws[ServletException]
  @throws[IOException]

  // Stripping newlines is not enough on its own: a lone carriage return still splits.
  @throws[ServletException]
  @throws[IOException]

  @throws[ServletException]
  @throws[IOException]
  override protected def doOptions(request: HttpServletRequest, response: HttpServletResponse): Unit = {
    val nickname = request.getParameter("nickname")
    response.setHeader("X-Profile", nickname)

    val replacedByANewline = nickname.replaceAll("\n", "\n")
    response.setHeader("X-Profile-Kept", replacedByANewline)

    val replacedByMoreInput = nickname.replaceAll("\n", request.getParameter("separator"))
    response.setHeader("X-Profile-Widened", replacedByMoreInput)

    val escaped = org.apache.commons.text.StringEscapeUtils.unescapeJava(nickname)
    response.setHeader("X-Profile-Escaped", escaped)

    val throughAPassthrough = identity(nickname)
    response.setHeader("X-Profile-Passed", throughAPassthrough)

    val wrapper = new HttpServletResponseWrapper(response)
    wrapper.addHeader("X-Profile-Added", nickname)
    wrapper.setHeader("X-Profile-Set", nickname)
  }

  private def identity(value: String) = value
}

Remediation

Follow secure coding practices and review the references below for detailed remediation guidance.

Configuration

This detector does not need any configuration.

References

© 2026 Xygeni. All rights reserved