Adding Valve workaround for GHSA-95v2-fvxr-qg83 - #12
Conversation
… suggestion for metacat<3.5.0
There was a problem hiding this comment.
Pull request overview
This PR introduces a Tomcat Valve implementation intended as a temporary mitigation for GHSA-95v2-fvxr-qg83 by rejecting requests whose URI/query contain path-traversal-style patterns (including across multiple URL-decoding rounds) before forwarding to the webapp.
Changes:
- Add
TemporaryMitigationValve(TomcatValveBase) that inspects request targets and denies suspicious patterns with HTTP 400. - Implement multi-round URL decoding to catch double-encoded traversal attempts.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… `null` when an illegal sequence is found
| private static final Pattern SUSPICIOUS = Pattern.compile( | ||
| "(?i)(\\.{2}|%2e|%2f|%5c|\\\\|/\\./|/\\.\\./|%252e|%252f|%255c)" | ||
| ); |
There was a problem hiding this comment.
Leaning towards erring on the stricter side unless others disagree
| private boolean isSuspicious(String input) { | ||
| String current = input; | ||
| for (int i = 0; i < MAX_DECODE_ROUNDS; i++) { | ||
| if (SUSPICIOUS.matcher(current).find()) { | ||
| return true; | ||
| } | ||
| String decoded = decodeOnce(current); | ||
| if (decoded == null) { | ||
| return true; | ||
| } | ||
| if (decoded.equals(current)) { | ||
| break; | ||
| } | ||
| current = decoded; | ||
| } | ||
| return SUSPICIOUS.matcher(current).find(); | ||
| } |
There was a problem hiding this comment.
Implemented in f7c7825 by adding focused JUnit coverage for TemporaryMitigationValve that exercises representative accepted and rejected request targets, including plain/encoded traversal and malformed % encoding cases.
There was a problem hiding this comment.
asked copilot to add unit tests
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…ity declarations in MIME multipart data, and adding accompanying tests
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
artntek
left a comment
There was a problem hiding this comment.
part-reviewed; will continue after dependencies fixed
| import jakarta.servlet.ServletException; | ||
| import jakarta.servlet.http.HttpServletResponse; |
There was a problem hiding this comment.
I believe jakarta.servlet.* is specific to Tomcat v10+. For Tomcat 9, these should instead be javax.servlet.*
| private final XmlSecurityValidationValve valve = new XmlSecurityValidationValve(); | ||
|
|
||
| @Test | ||
| public void identifiesXmlFromContentType() { |
There was a problem hiding this comment.
can we also assert some expected failures?
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
@artntek it's compiling cleanly for me now, and I added a couple of negative tests to the test suite. Let me know what else you find. Thank you! 🙏 |
artntek
left a comment
There was a problem hiding this comment.
looks good! One minor simplification
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||
| byte[] buffer = new byte[1024]; | ||
| ByteArrayOutputStream baos = new ByteArrayOutputStream( | ||
| declaredLength > 0 && declaredLength <= Integer.MAX_VALUE ? (int) declaredLength : 1024); |
There was a problem hiding this comment.
declaredLength <= Integer.MAX_VALUE is always true (so can be omitted, to simplify), because you already checked for if (declaredLength > maxRequestBytes) on line 46
This is a workaround for a soon-to-be-released advisory
GHSA-95v2-fvxr-qg83to be enabled in tomcat'sserver.xmlwith versions of metacat < 3.5.0. It uses a conservative URL pattern denial strategy to catch and deny potential filesystem path traversals in a request prior to being forwarded to the webapp. It is a temporary fix for affected installations (Metacat 3.4.2 and below) and is intended to be an intermediate step towards upgrading Metacat as soon as possible.Installation
Enable this module for the Metacat host by inserting the following line into
server.xml(in the<Host ...>element):Restart tomcat after the
Valveis in place: