CVE-2026-34151: XWiki Platform Old Core Path Traversal via /skin/ Endpoint on Jetty 12
A double-percent-encoded path in XWiki's /skin/ action lets any unauthenticated user read arbitrary files from the server filesystem, including /etc/passwd and WEB-INF config files, when running on…
The problem
The /bin/skin/ action in xwiki-platform-oldcore passes the request path to a resource loader without fully normalizing double-encoded traversal sequences before validating it. On Jetty 12+, the servlet container performs a second round of URI decoding, turning %252f first into %2f and then into /.
This lets an unauthenticated attacker escape the webapp root entirely. Reading /etc/passwd or sensitive files like WEB-INF/xwiki.cfg and WEB-INF/hibernate.cfg.xml requires no login and no special privileges. The default Docker image layout (webapp five levels below /) makes the full filesystem traversal reproducible out of the box.
Proof of concept
A working proof-of-concept for CVE-2026-34151 in org.xwiki.platform:xwiki-platform-oldcore, with the exact payload below.
# Read /etc/passwd (Docker image layout, webapp 5 levels below /)
GET /xwiki/bin/skin/..%252f/..%252f..%252f..%252f..%252f..%252f..%252f..%252fetc/passwd HTTP/1.1
Host: target.example.com
# Read WEB-INF config without leaving the webapp
GET /xwiki/bin/skin/..%252f/..%252fWEB-INF/xwiki.cfg HTTP/1.1
Host: target.example.comJetty 12 introduced a second URI normalization pass. The sequence %252f is first decoded to the literal string %2f by the application, then Jetty decodes %2f to /, producing an unintended directory separator that bypasses XWiki's existing traversal check.
The root cause is CWE-23: the skin action resolves the resource path against the filesystem before stripping or rejecting double-encoded dot-segments. The fix in xwiki-commons PR #1675 (XCOMMONS-3594) adds post-decode normalization and rejection of traversal patterns in the resource path handler, so the path is sanitized after all decoding rounds have occurred, not before.
The fix
Upgrade to XWiki 17.10.5 or 18.2.0. The fix is in xwiki-commons PR #1675 (XCOMMONS-3594). If you cannot upgrade immediately, switch to Tomcat or Jetty < 12 as a temporary workaround, since those containers are not affected by the double-decoding behavior.
Reported by Lê Ngọc Khoa.
Related research
- criticalCVE-2026-62263CVE-2026-62263: OpenAM WebAuthn ObjectInputFilter depth>1 Deserialization RCE
- critical · 9.8CVE-2026-62379CVE-2026-62379: OpenAM Unauthenticated Remote Code Execution via Unsafe Reflection in AuthXMLUtils
- high · 7.5http4s-blaze-server Unbounded WebSocket Message Aggregation DoS
- high · 7.5OmniFaces: Forged Resource IDs, XSS via o:hashParam, and Push-Channel Replay