Since the 9.0.96 version of the Apache Tomcat servlet container released on 2024-10-08 the c:out tag behaves differently and looks like it's a potential security issue (code injection ?)
It looks like in certain circumstances it does no longer escape the value
attribute.
Version 9.0.95 (and previous ones) does not have this behavior.
Here's how to reproduce the problem. Use a simple test file (use it as index.jsp
in the ROOT webapp for instance, along with taglibs-standard-impl-1.2.5.jar
and taglibs-standard-spec-1.2.5.jar
in the app's lib folder) :
<%@ page session="false" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String test = "{ \"key\" : \"value\" }";
java.util.Map<String, String> map = new java.util.HashMap<>();
map.put("test", test);
request.setAttribute("test", test);
request.setAttribute("map", map);
%>
<!DOCTYPE html>
<html lang="en">
<body>
<input type="text" name="test" id="test" value="<c:out value="${test}" />" />
<br/>
<input type="text" name="test" id="test" value="<c:out value="<%=test %>" />" />
<br/>
<c:forEach items="${map}" var="entry">
<input id="${entry.key}" name="${entry.key}" type="text" value="<c:out value="${entry.value}" />">
<br/>
</c:forEach>
<br/>
<br/>
Tomcat Version : <%= application.getServerInfo() %>
<br/>
Servlet Specification Version : <%= application.getMajorVersion() %>.<%= application.getMinorVersion() %>
<br/>
JSP version : <%=JspFactory.getDefaultFactory().getEngineInfo().getSpecificationVersion() %>
</body>
</html>
In Tomcat 9.0.95 it renders like this (showing just the important part) :
<input type="text" name="test" id="test" value="{ "key" : "value" }" />
<input type="text" name="test" id="test" value="{ "key" : "value" }" />
<input id="test" name="test" type="text" value="{ "key" : "value" }">
In Tomcat 9.0.96 it renders like this :
<input type="text" name="test" id="test" value="{ "key" : "value" }" />
<input type="text" name="test" id="test" value="{ "key" : "value" }" />
<input id="test" name="test" type="text" value="{ "key" : "value" }">
Even worse, when refreshing the page (the above result is obtained only once, after the JSP is compiled), then it renders like this :
<input type="text" name="test" id="test" value="{ "key" : "value" }" />
<input type="text" name="test" id="test" value="{ "key" : "value" }" />
<input id="test" name="test" type="text" value="{ "key" : "value" }">
After more extensive research, the problem, not directly linked to the described behavior can be found here :
https://bz.apache.org/bugzilla/show_bug.cgi?id=69399
Probably it's best to avoid 9.0.96 until it's fixed.