CVE-2026-50559
Patch Available.
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Quarkus is a Kubernetes-native Java framework optimized for cloud-native applications, containers, and serverless workloads. It is designed around fast startup, low memory use, build-time processing, and developer-friendly integrations across REST, HTTP, security, data, messaging, and observability extensions.
An Authorization Bypass vulnerability (CVE-2026-50559) has been identified in Quarkus HTTP security policy matching, which allows remote unauthenticated attackers to reach REST endpoints and static resources that path-based authentication and authorization policies were configured to protect. The bypass relies on encoded characters that the security layer and the request-serving layer interpret differently, so a single crafted request URI is enough to defeat the policy.
Per OWASP: Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification, or destruction of all data or performing a business function outside the user's limits.
This issue affects multiple versions of Quarkus that include the io.quarkus:quarkus-vertx-http package and rely on path-based HTTP security policies.
Details
Module Info
- Product: Quarkus
- Affected packages:
io.quarkus:quarkus-vertx-http - Affected versions: >=0 <3.20.6.2, >=3.21.0 <3.27.4.1, >=3.28.0 <3.33.2.1, >=3.34.0 <3.36.3, >=3.37.0.CR1 <3.37.0
- GitHub repository: https://github.com/quarkusio/quarkus
- Published packages: https://central.sonatype.com/artifact/io.quarkus/quarkus-vertx-http
- Package manager: Maven
- Fixed in: NES for Quarkus 2.16.12-quarkus-2.16.14; the NES 3.20.x line is based on Quarkus 3.20.6.2 and already carries the correction. Upstream community-supported lines were corrected in Quarkus 3.20.6.2, 3.27.4.1, 3.27.5, 3.33.2.1, 3.33.3, 3.36.3, and 3.37.0
Vulnerability Info
This High-severity vulnerability is found in the io.quarkus:quarkus-vertx-http package in multiple versions of Quarkus. Quarkus protects endpoints and static content with path-based HTTP security policies, configured through quarkus.http.auth.permission.*.paths, through @RolesAllowed on JAX-RS resources, through servlet constraints in web.xml, or through Keycloak policy enforcement. Every one of those mechanisms resolves the request path through the same matcher, and that matcher receives a path that has not been fully canonicalized.
In affected versions the matcher is handed Vert.x's normalizedPath(), optionally with semicolon-delimited matrix parameters stripped:
PathMatch<List<HttpMatcher>> toCheck = pathMatcher.match(HttpSecurityUtils.pathWithoutMatrixParams(routingContext.normalizedPath()));normalizedPath() decodes only the RFC 3986 unreserved characters, so a percent-encoded reserved character survives as literal text. An attacker who encodes the semicolon as %3B therefore reaches the matcher with a path segment such as admin%3Bbypass=true. The matrix-parameter helper searches for a literal semicolon, finds none, and returns the path untouched, so the segment no longer matches a policy written for /api/admin/* and the request proceeds with no authentication. Lowercase hex works identically, which makes the encoded form trivial to vary.
The same partial decoding creates a second and broader mismatch for static content, because the handlers that resolve files from the path decode it fully and fold backslashes to forward slashes before touching the filesystem:
String uriDecodedPath = URIDecoder.decodeURIComponent(context.normalizedPath(), false);String path = HttpUtils.removeDots(uriDecodedPath.replace('\\', '/'));An encoded slash, an encoded backslash, encoded dot segments, or a double encoding such as %252F survives the security layer intact but is resolved by the static handler, so the request fails to match the protecting policy and still returns the protected file. Exploitation requires only a single crafted HTTP request over the network, with no credentials and no user interaction, and working request vectors are published in the upstream advisory. The consequence is confidentiality loss: resources that the application intended to be non-public become readable, which matters most in deployments that serve sensitive static content and rely solely on path-based authorization.
Steps to Reproduce
- Deploy a Quarkus application in the affected range with two path policies that require authentication: one covering the endpoint path
/api/admin/*, and one covering the static resource path/secret/confidential.html. - Confirm that a direct request to
/api/admin/datais rejected, and that a direct request to/secret/confidential.htmlis rejected, because both policies apply. - Request the endpoint again with a percent-encoded semicolon in the protected segment, so that the policy matcher sees encoded text where routing sees a matrix parameter:
GET /api/admin%3Bbypass=true/data- The response is served without the authentication the policy required. Lowercase hex,
%3b, behaves identically. - Request the protected static resource with a double-encoded path separator, so that the first decoding pass yields
%2Fand the second yields a slash:
GET /secret%252Fconfidential.html- The static handler completes the decoding and returns the protected file, even though the policy matcher never saw a path that matched.
Mitigation
Only recent versions of Quarkus are community-supported. The affected 2.16.x line is End-of-Life and will not receive public updates to address this issue.
Users of the affected components should apply one of the following mitigations:
- Upgrade Quarkus to a currently supported release that contains the fix.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- Georgios Andrianakis (finder)