High severityNVD Advisory· Published Dec 28, 2022· Updated Apr 10, 2025
URL access filters bypass in Alpine
CVE-2022-23553
Description
Alpine is a scaffolding library in Java. Alpine prior to version 1.10.4 allows URL access filter bypass. This issue has been fixed in version 1.10.4. There are no known workarounds.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
us.springett:alpineMaven | < 1.10.4 | 1.10.4 |
Affected products
1- Range: < 1.10.4
Patches
1a7432184b913Added additional defences against URL filtering bypass
2 files changed · +70 −38
alpine/src/main/java/alpine/filters/BlacklistUrlFilter.java+27 −11 modified@@ -28,6 +28,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; /** * BlacklistUrlFilter is a configurable Servlet Filter that can prevent access to @@ -103,21 +105,35 @@ public void doFilter(final ServletRequest request, final ServletResponse respons final HttpServletRequest req = (HttpServletRequest) request; final HttpServletResponse res = (HttpServletResponse) response; - - final String requestUri = req.getRequestURI(); - if (requestUri != null) { - for (final String url: denyUrls) { - if (requestUri.startsWith(url.trim())) { - res.setStatus(HttpServletResponse.SC_FORBIDDEN); + try { + // Canonicalize the URI + final String requestUri = new URI(req.getRequestURI()).normalize().getPath(); + if (requestUri != null) { + // If the canonicalized URI still contains the '..' sequence, a potentially malicious request + // has been made. Respond with a 400. NOTE: Jetty/Embedded already has protections against this, + // therefore, the following code should never be true. But in the event Jetty changes in the future, + // this code is left here as an additional layer of defense. + // See: https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/http/HttpComplianceSection.html#NO_AMBIGUOUS_PATH_PARAMETERS + if (requestUri.contains("..")) { + res.setStatus(HttpServletResponse.SC_BAD_REQUEST); return; } - } - for (final String url: ignoreUrls) { - if (requestUri.startsWith(url.trim())) { - res.setStatus(HttpServletResponse.SC_NOT_FOUND); - return; + for (final String url: denyUrls) { + if (requestUri.startsWith(url.trim())) { + res.setStatus(HttpServletResponse.SC_FORBIDDEN); + return; + } + } + for (final String url: ignoreUrls) { + if (requestUri.startsWith(url.trim())) { + res.setStatus(HttpServletResponse.SC_NOT_FOUND); + return; + } } } + } catch (URISyntaxException e) { + res.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; } chain.doFilter(request, response); }
alpine/src/main/java/alpine/filters/WhitelistUrlFilter.java+43 −27 modified@@ -28,6 +28,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Arrays; /** @@ -111,40 +113,54 @@ public void doFilter(final ServletRequest request, final ServletResponse respons final HttpServletRequest req = (HttpServletRequest) request; final HttpServletResponse res = (HttpServletResponse) response; - - final String requestUri = req.getRequestURI(); - if (requestUri != null) { - boolean allowed = false; - final String requestUrlExcludingContext = requestUri.substring(req.getContextPath().length()); - for (final String url: allowUrls) { - if (requestUrlExcludingContext.equals("/")) { - if (url.trim().equals("/") || (url.trim().equals("/index.jsp")) || (url.trim().equals("/index.html"))) { + try { + // Canonicalize the URI + final String requestUri = new URI(req.getRequestURI()).normalize().getPath(); + if (requestUri != null) { + // If the canonicalized URI still contains the '..' sequence, a potentially malicious request + // has been made. Respond with a 400. NOTE: Jetty/Embedded already has protections against this, + // therefore, the following code should never be true. But in the event Jetty changes in the future, + // this code is left here as an additional layer of defense. + // See: https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/http/HttpComplianceSection.html#NO_AMBIGUOUS_PATH_PARAMETERS + if (requestUri.contains("..")) { + res.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } + boolean allowed = false; + final String requestUrlExcludingContext = requestUri.substring(req.getContextPath().length()); + for (final String url: allowUrls) { + if (requestUrlExcludingContext.equals("/")) { + if (url.trim().equals("/") || (url.trim().equals("/index.jsp")) || (url.trim().equals("/index.html"))) { + allowed = true; + } + } else if (requestUrlExcludingContext.startsWith(url.trim())) { allowed = true; } - } else if (requestUrlExcludingContext.startsWith(url.trim())) { - allowed = true; } - } - if (!allowed) { - if (forwardTo != null) { - for (final String url: allowUrls) { - if (forwardExcludes != null && Arrays.stream(forwardExcludes).anyMatch(url::equals)) { - break; - } - final int occurrence = requestUrlExcludingContext.indexOf(url); - if (occurrence > -1) { - final String queryString = (req.getQueryString() == null) ? "" : "?" + req.getQueryString(); - final String resourceUrl = requestUrlExcludingContext.substring(occurrence) + queryString; - req.getRequestDispatcher(resourceUrl).forward(request, response); - return; + if (!allowed) { + if (forwardTo != null) { + for (final String url: allowUrls) { + if (forwardExcludes != null && Arrays.stream(forwardExcludes).anyMatch(url::equals)) { + break; + } + final int occurrence = requestUrlExcludingContext.indexOf(url); + if (occurrence > -1) { + final String queryString = (req.getQueryString() == null) ? "" : "?" + req.getQueryString(); + final String resourceUrl = requestUrlExcludingContext.substring(occurrence) + queryString; + req.getRequestDispatcher(resourceUrl).forward(request, response); + return; + } } + req.getRequestDispatcher(forwardTo).forward(request, response); + } else { + res.setStatus(HttpServletResponse.SC_NOT_FOUND); } - req.getRequestDispatcher(forwardTo).forward(request, response); - } else { - res.setStatus(HttpServletResponse.SC_NOT_FOUND); + return; } - return; } + } catch (URISyntaxException e) { + res.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; } chain.doFilter(request, response); }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-2w4p-2hf7-gh8xghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-23553ghsaADVISORY
- securitylab.github.com/advisories/GHSL-2021-1009-AlpineghsaADVISORY
- github.com/stevespringett/Alpine/blob/alpine-parent-1.10.2/alpine/src/main/java/alpine/filters/BlacklistUrlFilter.javaghsax_refsource_MISCWEB
- github.com/stevespringett/Alpine/blob/alpine-parent-1.10.2/alpine/src/main/java/alpine/filters/WhitelistUrlFilter.javaghsax_refsource_MISCWEB
- github.com/stevespringett/Alpine/commit/a7432184b9137ea095799a77f9ced370553acbd7ghsaWEB
- github.com/stevespringett/Alpine/releases/tag/alpine-parent-1.10.4ghsaWEB
- securitylab.github.com/advisoriesghsaWEB
- securitylab.github.com/advisories/GHSL-2021-1009-Alpine/mitrex_refsource_CONFIRM
News mentions
0No linked articles in our index yet.