CVE-2026-18661

Authorization Bypass
Affects
Eclipse Jetty
in
Jetty
No items found.
Versions
>=9.4.0 <=9.4.64, >=10.0.0 <=10.0.32, >=11.0.0 <=11.0.32, >=12.0.0 <=12.0.38, >=12.1.0 <=12.1.11

Patch Available.

Exclamation circle icon
Patch Available

This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.

Overview

Eclipse Jetty is a widely used, embeddable Java web server and servlet container. It supports HTTP/1.1, HTTP/2, HTTP/3, and WebSocket, and is commonly deployed both as a standalone server and embedded within Java application runtimes and frameworks. Its jetty-annotations module scans web application classes for Servlet annotations, including @ServletSecurity, and turns them into security constraints.

An authorization bypass vulnerability (CVE-2026-18661) has been identified in the jetty-annotations module of Eclipse Jetty, which allows attackers to reach a servlet through an alternate URL mapping that its @ServletSecurity annotation should protect. When the deployment descriptor constrains only some of a servlet's URL patterns, Jetty ignores the annotation for all of them, leaving the other mappings unconstrained.

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 Eclipse Jetty.

‍

Details

Module Info

  • Product: Eclipse Jetty
  • Affected packages: org.eclipse.jetty:jetty-annotations, org.eclipse.jetty.ee8:jetty-ee8-annotations, org.eclipse.jetty.ee9:jetty-ee9-annotations, org.eclipse.jetty.ee10:jetty-ee10-annotations, org.eclipse.jetty.ee11:jetty-ee11-annotations
  • Affected versions:
    • org.eclipse.jetty:jetty-annotations: >=9.4.0 <=9.4.64, >=10.0.0 <=10.0.32, >=11.0.0 <=11.0.32
    • org.eclipse.jetty.ee8:jetty-ee8-annotations: >=12.0.0 <=12.0.38, >=12.1.0 <=12.1.11
    • org.eclipse.jetty.ee9:jetty-ee9-annotations: >=12.0.0 <=12.0.38, >=12.1.0 <=12.1.11
    • org.eclipse.jetty.ee10:jetty-ee10-annotations: >=12.0.0 <=12.0.38, >=12.1.0 <=12.1.11
    • org.eclipse.jetty.ee11:jetty-ee11-annotations: >=12.1.0 <=12.1.11
  • GitHub repository: https://github.com/jetty/jetty.project
  • Published packages: https://central.sonatype.com/artifact/org.eclipse.jetty/jetty-annotations
  • Package manager: Maven
  • Fixed in:
    • OSS Eclipse Jetty 12.0.39, 12.1.12
    • NES for Jetty v9.4.65, v10.0.33, v11.0.33

Vulnerability Info

This High-severity vulnerability is found in the jetty-annotations package in multiple versions of Eclipse Jetty (and the jetty-eeN-annotations packages in Jetty 12). ServletSecurityAnnotationHandler.doHandle() collects every URL mapping of a servlet annotated with @ServletSecurity and every constraint mapping already defined by the deployment descriptor, then runs one aggregate check before it creates any annotation constraints:

List<ServletMapping> servletMappings = getServletMappings(clazz.getCanonicalName());
List<ConstraintMapping> constraintMappings = ((ConstraintAware)_context.getSecurityHandler()).getConstraintMappings();

if (constraintsExist(servletMappings, constraintMappings))
{
    LOG.warn("Constraints already defined for " + clazz.getName() + ", skipping ServletSecurity annotation");
    return;
}

constraintsExist() returns true as soon as any one of the servlet's path specs equals the path spec of any existing security-constraint. The early return then drops the whole annotation, so no constraints are generated for the servlet's other URL patterns.

The Servlet specification gives a descriptor constraint precedence only for the exact URL pattern it names; the annotation must still apply to the servlet's remaining patterns. When a web.xml maps one servlet to several URL patterns but constrains only some of them, the unconstrained patterns are served with no access control at all. An unauthenticated remote attacker can request the servlet through one of those alternate mappings and bypass the roles or DENY semantics its @ServletSecurity annotation declares. Depending on the servlet, this can disclose sensitive data or allow unauthorized state-changing operations. Applications whose descriptor explicitly constrains every mapping of the annotated servlet are not affected.

‍

Steps to Reproduce

1. Create a servlet that denies all access through its annotation (on Jetty 9.4, Jetty 10, and the Jetty 12 ee8 environment, import from javax.servlet instead of jakarta.servlet):

package poc;

import java.io.IOException;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.HttpConstraint;
import jakarta.servlet.annotation.ServletSecurity;
import jakarta.servlet.annotation.ServletSecurity.EmptyRoleSemantic;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@ServletSecurity(@HttpConstraint(value = EmptyRoleSemantic.DENY))
public class DeniedServlet extends HttpServlet
{
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        response.setContentType("text/plain");
        response.getWriter().print("ANNOTATED_SERVLET_EXECUTED");
    }
}

2. In the WAR's WEB-INF/web.xml, map the servlet to two URL patterns and add a security-constraint for only one of them:

<servlet>
  <servlet-name>denied</servlet-name>
  <servlet-class>poc.DeniedServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>denied</servlet-name>
  <url-pattern>/descriptor</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>denied</servlet-name>
  <url-pattern>/annotation-only</url-pattern>
</servlet-mapping>

<security-constraint>
  <web-resource-collection>
    <web-resource-name>Descriptor-only denial</web-resource-name>
    <url-pattern>/descriptor</url-pattern>
  </web-resource-collection>
  <auth-constraint/>
</security-constraint>

3. Deploy the WAR at context path / on an affected Jetty with annotation scanning enabled, and send unauthenticated GET requests to /descriptor and /annotation-only.

4. Jetty logs Constraints already defined for poc.DeniedServlet, skipping ServletSecurity annotation. The request to /descriptor returns 403, but the request to /annotation-only returns 200 with the body ANNOTATED_SERVLET_EXECUTED, even though the annotation denies every request.

‍

Mitigation

Only recent versions of Eclipse Jetty are community-supported. Only community-supported versions will receive updates to address this issue. As of January 1, 2026 the Jetty project and Webtide no longer publish Jetty 9, Jetty 10, or Jetty 11 releases to Maven Central; see the project's End-of-Life announcement.

Users of the affected components should apply one of the following mitigations:

  • Upgrade affected applications to a supported version of Eclipse Jetty (12.0.39 or 12.1.12).
  • Leverage a commercial support partner like HeroDevs for post-EOL security support.

‍

Credits

Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
High
ID
CVE-2026-18661
PROJECT Affected
Eclipse Jetty
Versions Affected
>=9.4.0 <=9.4.64, >=10.0.0 <=10.0.32, >=11.0.0 <=11.0.32, >=12.0.0 <=12.0.38, >=12.1.0 <=12.1.11
NES Versions Affected
Published date
October 15, 2026
≈ Fix date
October 15, 2026
Category
Authorization Bypass
Vex Document
Download VEXHow do I use it?
Sign up for the latest vulnerability alerts fixed in
NES for Jetty
Rss feed icon
Subscribe via RSS
or

By submitting the form I acknowledge receipt of our Privacy Policy.

Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.