I ran into a false negative in the Java URL redirection queries for a common Spring MVC pattern.
java/unvalidated-url-redirection does not appear to cover redirects expressed through Spring view names like return "redirect:" + userControlledValue, especially when that construction is wrapped in a helper method.
I found this on a public CVE, CVE-2025-8813, in atjiu/pybbs.
Vulnerable code:
@GetMapping("changeLanguage")
public String changeLanguage(String lang, HttpSession session, HttpServletRequest request) {
String referer = request.getHeader("referer");
if ("zh".equals(lang)) {
session.setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, Locale.SIMPLIFIED_CHINESE);
} else if ("en".equals(lang)) {
session.setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, Locale.US);
}
return StringUtils.isEmpty(referer) ? redirect("/") : redirect(referer);
}
protected String redirect(String path) {
return "redirect:" + path;
}
This was fixed upstream by removing the user-controlled redirect target:
atjiu/pybbs@edb14ff
My understanding is that the stable query covers servlet-style redirect sinks such as sendRedirect(...) and Location headers, but not the Spring MVC redirect-by-view-name sink family. In this case the source is straightforward (request.getHeader("referer")) and the flow is short, so the gap seems to be sink coverage rather than source modeling.
This pattern is common in practice:
return "redirect:" + next
return new ModelAndView("redirect:" + next)
return new RedirectView(next)
- helper wrappers such as
redirect(next) in a base controller or utility class
That last form is especially common in real Spring code, so this is not just a one-off CVE shape. I would expect similar misses whenever a project centralizes redirect construction in a helper.
There is already an experimental query, java/spring-unvalidated-url-redirection, so this may just be a case where the relevant Spring sink modeling has not made it into the stable query set yet.
A reasonable fix might be to bring the Spring redirect sink coverage into the stable rule family, especially for:
"redirect:" + tainted
new ModelAndView("redirect:" + tainted)
new RedirectView(tainted)
- helper-mediated variants that ultimately construct a Spring redirect view name
I ran into a false negative in the Java URL redirection queries for a common Spring MVC pattern.
java/unvalidated-url-redirectiondoes not appear to cover redirects expressed through Spring view names likereturn "redirect:" + userControlledValue, especially when that construction is wrapped in a helper method.I found this on a public CVE,
CVE-2025-8813, inatjiu/pybbs.Vulnerable code:
This was fixed upstream by removing the user-controlled redirect target:
atjiu/pybbs@edb14ff
My understanding is that the stable query covers servlet-style redirect sinks such as
sendRedirect(...)andLocationheaders, but not the Spring MVC redirect-by-view-name sink family. In this case the source is straightforward (request.getHeader("referer")) and the flow is short, so the gap seems to be sink coverage rather than source modeling.This pattern is common in practice:
return "redirect:" + nextreturn new ModelAndView("redirect:" + next)return new RedirectView(next)redirect(next)in a base controller or utility classThat last form is especially common in real Spring code, so this is not just a one-off CVE shape. I would expect similar misses whenever a project centralizes redirect construction in a helper.
There is already an experimental query,
java/spring-unvalidated-url-redirection, so this may just be a case where the relevant Spring sink modeling has not made it into the stable query set yet.A reasonable fix might be to bring the Spring redirect sink coverage into the stable rule family, especially for:
"redirect:" + taintednew ModelAndView("redirect:" + tainted)new RedirectView(tainted)