Source:
<code>public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { final HttpServletRequest httpRequest = (HttpServletRequest) request; ensureSessionHasToken(httpRequest.getSession(false)); switch (httpRequest.getMethod().toUpperCase()) { case "POST": case "PUT": case "DELETE": { if (CSRFTokenCheck.INSTANCE.isInsecure(httpRequest, log)) { CSRFTokenCheck.INSTANCE.prepareResponse(httpRequest, (HttpServletResponse) response, log); return; } } case "GET": { final HttpServletResponse responseWrapper = noCache(getCharResponseWrapper((HttpServletResponse) response)); chain.doFilter(httpRequest, responseWrapper); final HttpSession session = httpRequest.getSession(false); final byte[] bytes; final String output; final String responseContentType = responseWrapper.getContentType(); if (session != null && responseContentType != null && responseContentType.toLowerCase().startsWith("text/html")) { CSRFTokenCheck.INSTANCE.prepareSession(session, log); final Document document = Jsoup.parse(responseWrapper.toString()); String injectedScript = "<script>var " + ERRAI_CSRF_TOKEN_VAR + " = '" + CSRFTokenCheck.getToken(session) + "';</script>"; document.head().prepend(injectedScript); output = document.html(); bytes = output.getBytes("UTF-8"); } else { output = responseWrapper.toString(); bytes = output.getBytes("UTF-8"); } response.setContentLength(bytes.length); <START> if (isOuputStream) { <END> response.getOutputStream().write(bytes); } else { response.getWriter().print(output); } return; } } chain.doFilter(request, response); }</code><technical_language>Testing old/error behavior is needed, tests good for testing actual fix works. Please remove output stream call</technical_language>

Target:
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { final HttpServletRequest httpRequest = (HttpServletRequest) request; ensureSessionHasToken(httpRequest.getSession(false)); switch (httpRequest.getMethod().toUpperCase()) { case "POST": case "PUT": case "DELETE": { if (CSRFTokenCheck.INSTANCE.isInsecure(httpRequest, log)) { CSRFTokenCheck.INSTANCE.prepareResponse(httpRequest, (HttpServletResponse) response, log); return; } } case "GET": { final HttpServletResponse responseWrapper = noCache(getCharResponseWrapper((HttpServletResponse) response)); chain.doFilter(httpRequest, responseWrapper); final HttpSession session = httpRequest.getSession(false); final byte[] bytes; final String output; final String responseContentType = responseWrapper.getContentType(); if (session != null && responseContentType != null && responseContentType.toLowerCase().startsWith("text/html")) { CSRFTokenCheck.INSTANCE.prepareSession(session, log); final Document document = Jsoup.parse(responseWrapper.toString()); String injectedScript = "<script>var " + ERRAI_CSRF_TOKEN_VAR + " = '" + CSRFTokenCheck.getToken(session) + "';</script>"; document.head().prepend(injectedScript); output = document.html(); } else { output = responseWrapper.toString(); } bytes = output.getBytes("UTF-8"); response.setContentLength(bytes.length); response.getWriter().print(output); return; } } chain.doFilter(request, response); }