Summary
WebUtils.getPathWithinApplication() can return null when the request path normalizes above root. This null propagates through PathMatchingFilterChainResolver.getChain() which cannot match any pattern (including /**), and AbstractShiroFilter.getExecutionChain() falls back to the original container FilterChain — bypassing all Shiro security filters.
Root Cause
Commit b90f918 (Shiro 1.5.3, CVE-2020-11989 fix) changed getPathWithinApplication() to:
return normalize(removeSemicolon(getServletPath(request) + getPathInfo(request)));
normalize() returns null when the path contains /../ at index 0 (trying to go above root). Unlike the old implementation (which always returned a valid path), this null is never handled downstream.
Impact
Complete authentication and authorization bypass. Requests that trigger this code path skip InvalidRequestFilter, authc, roles/perms, and all other Shiro filters. The downstream framework (Spring, JAX-RS, etc.) routes the request normally.
Attack Vector
An attacker sends a request where getServletPath() + getPathInfo() produces a path where normalize() returns null (e.g. path traversal above root). When the servlet container does not normalize the path before passing it to filters (some containers, configurations, or via RequestDispatcher.forward/include), this causes Shiro to skip all security checks.
Affected Versions
Shiro 1.5.3 through 3.0.0 — all versions since the normalize() call was introduced in getPathWithinApplication().
Suggested Fix
Return "/" instead of null from getPathWithinApplication() when normalize() fails, and add a /** fallback in PathMatchingFilterChainResolver. A PR with the fix and tests is available at #2836.
Summary
WebUtils.getPathWithinApplication()can returnnullwhen the request path normalizes above root. Thisnullpropagates throughPathMatchingFilterChainResolver.getChain()which cannot match any pattern (including/**), andAbstractShiroFilter.getExecutionChain()falls back to the original containerFilterChain— bypassing all Shiro security filters.Root Cause
Commit b90f918 (Shiro 1.5.3, CVE-2020-11989 fix) changed
getPathWithinApplication()to:normalize()returnsnullwhen the path contains/../at index 0 (trying to go above root). Unlike the old implementation (which always returned a valid path), this null is never handled downstream.Impact
Complete authentication and authorization bypass. Requests that trigger this code path skip
InvalidRequestFilter, authc, roles/perms, and all other Shiro filters. The downstream framework (Spring, JAX-RS, etc.) routes the request normally.Attack Vector
An attacker sends a request where
getServletPath() + getPathInfo()produces a path wherenormalize()returns null (e.g. path traversal above root). When the servlet container does not normalize the path before passing it to filters (some containers, configurations, or viaRequestDispatcher.forward/include), this causes Shiro to skip all security checks.Affected Versions
Shiro 1.5.3 through 3.0.0 — all versions since the normalize() call was introduced in
getPathWithinApplication().Suggested Fix
Return
"/"instead ofnullfromgetPathWithinApplication()whennormalize()fails, and add a/**fallback inPathMatchingFilterChainResolver. A PR with the fix and tests is available at #2836.