Skip to content

Adding Valve workaround for GHSA-95v2-fvxr-qg83 - #12

Open
iannesbitt wants to merge 16 commits into
mainfrom
advisory-patch-2026-07-01
Open

Adding Valve workaround for GHSA-95v2-fvxr-qg83#12
iannesbitt wants to merge 16 commits into
mainfrom
advisory-patch-2026-07-01

Conversation

@iannesbitt

Copy link
Copy Markdown

This is a workaround for a soon-to-be-released advisory GHSA-95v2-fvxr-qg83 to be enabled in tomcat's server.xml with 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):

     <Valve className="org.dataone.security.TemporaryMitigationValve" />

Restart tomcat after the Valve is in place:

systemctl restart tomcat9

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 (Tomcat ValveBase) 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.

Comment thread src/main/java/org/dataone/security/TemporaryMitigationValve.java Outdated
Comment thread src/main/java/org/dataone/security/TemporaryMitigationValve.java Outdated
Comment thread src/main/java/org/dataone/security/TemporaryMitigationValve.java Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 4 comments.

Comment thread src/main/java/org/dataone/security/TemporaryMitigationValve.java Outdated
Comment thread src/main/java/org/dataone/security/TemporaryMitigationValve.java Outdated
Comment on lines +48 to +50
private static final Pattern SUSPICIOUS = Pattern.compile(
"(?i)(\\.{2}|%2e|%2f|%5c|\\\\|/\\./|/\\.\\./|%252e|%252f|%255c)"
);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaning towards erring on the stricter side unless others disagree

Comment on lines +69 to +85
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();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asked copilot to add unit tests

iannesbitt and others added 2 commits July 10, 2026 13:32
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…ity declarations in MIME multipart data, and adding accompanying tests

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

Comment thread src/main/java/org/dataone/security/XmlSecurityValidationValve.java Outdated
Comment thread src/main/java/org/dataone/security/XmlSecurityValidationValve.java Outdated
Comment thread src/main/java/org/dataone/security/XmlSecurityValidationValve.java Outdated
Comment thread src/main/java/org/dataone/security/XmlSecurityValidationValve.java
Comment thread src/main/java/org/dataone/security/XmlSecurityValidationValve.java
iannesbitt and others added 3 commits July 13, 2026 07:30
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 artntek left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

part-reviewed; will continue after dependencies fixed

Comment thread src/main/java/org/dataone/security/XmlSecurityValidationValve.java Outdated
Comment thread src/main/java/org/dataone/security/XmlSecurityValidationValve.java Outdated
Comment thread src/test/java/org/dataone/security/XmlSecurityValidationValveTest.java Outdated
Comment on lines +35 to +36
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletResponse;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe jakarta.servlet.* is specific to Tomcat v10+. For Tomcat 9, these should instead be javax.servlet.*

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed these in bb952c7

private final XmlSecurityValidationValve valve = new XmlSecurityValidationValve();

@Test
public void identifiesXmlFromContentType() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we also assert some expected failures?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding these shortly...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added tests with broken xml in 41a1852

iannesbitt and others added 2 commits August 11, 2026 12:56
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@iannesbitt
iannesbitt requested a review from artntek August 11, 2026 20:05
@iannesbitt

Copy link
Copy Markdown
Author

@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 artntek left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

declaredLength <= Integer.MAX_VALUE is always true (so can be omitted, to simplify), because you already checked for if (declaredLength > maxRequestBytes) on line 46

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants