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.
References
-
OWASP Top 10 2025 - A01 : Broken Access Control.