Apache Axis2/Java is a SOAP and REST web services engine. It provides a message-processing pipeline with pluggable transports (HTTP/HTTPS, JMS, TCP, local), a module system for cross-cutting concerns (WS-Security via Rampart, WS-Addressing), hot-deployment of service archives (AAR/MAR), and multi-protocol serving (JSON-RPC, REST/OpenAPI, MCP) from a single service deployment. It runs inside a Jakarta Servlet container (Tomcat, Jetty, WildFly) or embedded via Spring Boot.
| Role | Trust Level | Description |
|---|---|---|
| Server Administrator | Fully trusted | Configures axis2.xml, deploys/removes modules and services, controls the servlet container. Has filesystem and JVM-level access. |
| Service Deployer | Trusted | Drops AAR archives into WEB-INF/services/. May be the same person as the administrator, or a CI pipeline. |
| Module Developer | Trusted | Builds and deploys MAR module archives that add handlers to the processing pipeline. Code executes with full JVM privileges. |
| Authenticated Client | Partially trusted | A remote caller whose identity has been verified by the servlet container, a servlet filter, or a WS-Security module (Rampart). Authorized actions depend on the application. |
| Anonymous Client | Untrusted | A remote caller with no credentials. Can reach any endpoint exposed by the HTTP transport. All input is hostile. |
WEB-INF/services/ or WEB-INF/modules/, they can deploy arbitrary code. This is an OS/container configuration issue./services/ listing. When exposeServiceMetadata is true (the default), service names are visible. This is documented behavior controllable via axis2.xml.Remote Client (untrusted input)
|
v
Servlet Container (TLS termination, optional authentication)
|
v
AxisServlet / HTTPWorker <-- HTTP entry point
|
v
MessageContext created <-- request metadata captured
|
v
Transport-In Phase <-- transport-level handlers
|
v
Dispatchers <-- route to service/operation
(URI, SOAPAction, WS-Addressing, JSON method, HTTP location)
|
v
Handler Phases <-- global + per-service handlers
(security modules like Rampart execute here)
|
v
Message Builder <-- deserialize body
(SOAP, XML, JSON, MTOM, multipart/form-data)
|
v
MessageReceiver <-- invoke service method
|
v
Response Phases + Transport-Out <-- serialize response, send
Axis2 exposes the following URL patterns from the servlet mapping:
| Pattern | Purpose | Trust Requirement |
|---|---|---|
/services/{ServiceName} | JSON-RPC and SOAP service invocation | Application-defined |
/services/{ServiceName}/{Operation} | REST-style per-operation invocation | Application-defined |
/services/{ServiceName}?wsdl | WSDL metadata retrieval | Anonymous (if exposeServiceMetadata=true) |
/services/{ServiceName}?xsd | XML Schema retrieval | Anonymous (if exposeServiceMetadata=true) |
/services/ | Service listing | Anonymous (if exposeServiceMetadata=true) |
/services/{ServiceName}/{name}.xsd or .wsdl | Packaged metadata by file name | Anonymous (if exposeServiceMetadata=true) |
/openapi.json | OpenAPI 3.0 schema (if OpenAPI module engaged) | Anonymous; per-service exposeServiceMetadata respected |
/swagger-ui | Swagger UI (if OpenAPI module engaged) | Anonymous; per-service exposeServiceMetadata respected |
/openapi-mcp.json | MCP tool catalog (if OpenAPI module engaged) | Anonymous; per-service exposeServiceMetadata respected |
| Component | Threats | Mitigations |
|---|---|---|
| XML parsers (AXIOM/StAX, DocumentBuilderFactory) | XXE, billion laughs, entity expansion DoS | DOCTYPE disallowed; external entities disabled; DefaultEntityResolver returns empty source |
| WSDL/XSD import resolution (wsdl4j, xmlschema-core) | XXE in imported documents; SSRF via file:///gopher:// schemes | SecureWSDLLocator pre-validates with hardened SAX parser; protocol whitelist (HTTP/HTTPS only); size limit (10MB default); connect/read timeouts; relative-path SSRF bypass blocked |
| JSON parser (Gson) | Deep nesting stack exhaustion, large payload DoS | Fuzz-tested (1.7M+ iterations); Gson nesting limits |
| JSON-RPC dispatch | Method name injection; unexpected operation invocation | Method names validated against deployed operations; unknown methods return fault |
| Multipart/file upload (commons-fileupload2) | Unbounded file count DoS (CVE-2023-24998 pattern); unbounded body size; temp-file accumulation | commons-fileupload2 enforces the file count limit; multipartMaxRequestSize / multipartMaxFileSize bound the body; temp files are deleted immediately for form fields and tracked to collection for file parts |
| Form-urlencoded builder | Unbounded body read into an in-memory map | formUrlEncodedMaxRequestSize bounds the read; the stream fails rather than truncating |
| Service dispatchers | Routing to unintended service; header spoofing | Dispatchers validate service existence; unknown services return fault |
| Hot-deployment (DeploymentEngine) | Malicious AAR/MAR deploys arbitrary code | Trust boundary is filesystem access; no signature verification (admin operation) |
| Context externalization (SafeObjectInputStream) | Java deserialization gadget chains | Whitelist-based SafeObjectInputStream; restricted to known Axis2 context classes |
Metadata endpoints (?wsdl, ?xsd, /services/, .xsd/.wsdl by name, OpenAPI/MCP) | Service enumeration, schema disclosure | exposeServiceMetadata enforced uniformly across the servlet and standalone HTTP paths and the OpenAPI/MCP generators |
WS-Addressing response endpoints (wsa:ReplyTo, wsa:FaultTo) | SSRF: an inbound header names the destination of a server-initiated send | Non-anonymous response endpoints refused by default (allowNonAnonymousResponseEndpoints); when enabled, scheme restricted to HTTPS, destination screened at both the header-parsing and transport-selection layers, and redirects not followed |
| OpenAPI / Swagger UI surface | Reflected XSS from request-controlled values; Host reflected into published URLs | Host validated, values encoded for their output context, CSP with a per-response script nonce; the published servers[].url is relative unless openapi.serverBaseUrl pins it |
| MTOM/attachment handling | Large attachment DoS, temp file exhaustion | Streaming processing; TempFileManager cleanup |
?fields= query parameter (field selection, if enabled) | Reflection-based field filtering on response objects | Field names validated against declared response type; no dynamic class loading |
| Transport | Security Notes |
|---|---|
| HTTP/HTTPS | TLS handled by servlet container. No framework-level auth. Primary production transport. |
| Local (in-JVM) | No network exposure. JVM-level isolation only. |
| JMS | Authentication delegated to JMS broker. |
| TCP | Raw sockets. No encryption or authentication. Trusted networks only. |
| UDP | No encryption, no authentication, no reliability. Trusted networks only. |
| Depends on mail server authentication. |
Axis2's CVE history concentrates in three categories. The scan should weight these areas accordingly.
Clustering module (removed): A previous version of Axis2 included a clustering module for multi-node coordination using Apache Tribes. This module exposed a network listener that deserialized Java objects from untrusted network streams without validation, enabling Remote Code Execution (RCE) via standard deserialization gadget chains. This affected all releases through 2.0.0 on Apache Tomcat, but only when the Tribes-based clustering feature was manually enabled (it was off by default). Assigned CVE-2026-66713 and resolved by complete removal of the clustering module in 40+ files (AXIS2-6097) in release 2.0.1.
Lesson: Any ObjectInputStream.readObject() on network input is a critical-severity finding. The remaining use of Java serialization in Axis2 is SafeObjectInputStream for context externalization, which uses a class whitelist.
CVE-2010-1632: DTD/XXE in MTOMBuilder flow. Fixed by strictly forbidding DOCTYPE declarations in SOAP and XML requests.
WSDL import parsing: wsdl4j 1.6.3 creates its own DocumentBuilderFactory without XXE hardening. Axis2 mitigates this with SecureWSDLLocator (pre-validates imported documents with a hardened SAX parser, rejects DOCTYPE, protocol-whitelists to HTTP/HTTPS, enforces size limits and timeouts) and hardened URI resolvers for xmlschema-core imports.
Lesson: Third-party XML libraries (wsdl4j, xmlschema-core) create their own parser factories that bypass framework-level hardening. Every XML parsing path — including transitive ones through dependency libraries — must be audited.
| CVE | Dependency | Issue | Resolution |
|---|---|---|---|
| CVE-2010-3981 | Admin console | CSRF/XSS | Fixed in 1.7.3 |
| CVE-2012-6153, CVE-2014-3577 | Apache HttpClient | Various | Updated dependency in 1.7.4 |
| CVE-2016-1000031 | commons-fileupload | RCE via DiskFileItem | Updated dependency in 1.7.6 |
| CVE-2023-24998 | commons-fileupload 1.x | Unbounded file count DoS | Migrated to commons-fileupload2 in 2.0.0 |
Lesson: Dependency-level CVEs are the most frequent class. The migration from commons-fileupload 1.x to commons-fileupload2 in 2.0.0 was specifically driven by CVE-2023-24998.
XML parsing: All DocumentBuilderFactory and SAXParserFactory instances created by the framework disable DTDs and external entities (XMLUtils.java, SecureWSDLLocator.java, DefaultEntityResolver.java).
WSDL import security: SecureWSDLLocator pre-parses imported documents before passing them to wsdl4j. Protocol-restricted to HTTP/HTTPS. Size-limited. Timeout-protected. Relative-path SSRF bypass patched.
Schema import security: URI resolvers for AAR and WAR deployments block HTTP/HTTPS/FTP/JAR/file scheme resolution to prevent SSRF via xmlschema-core's DefaultURIResolver.
Deserialization whitelist: SafeObjectInputStream restricts Java object deserialization to known Axis2 context classes.
Clustering removed: The entire clustering module (Tribes-based inter-node communication with unvalidated deserialization) has been removed from the codebase.
File upload limits: Migration to commons-fileupload2 enforces file count limits, preventing CVE-2023-24998-style DoS.
Fault detail suppression: sendStacktraceDetailsWithFaults defaults to false.
Fuzz testing: Jazzer-based fuzzers cover XML, JSON, HTTP header, and URL parsers. 45M+ iterations with zero crashes or security findings. See src/site/xdoc/docs/OSS-FUZZ.md. Axis2/C has an active OSS-Fuzz integration.
WS-Addressing response endpoints (2.0.2): A non-anonymous wsa:ReplyTo or wsa:FaultTo makes the server open a connection to an address the caller chose. Unless WS-Security is engaged to bind that endpoint reference to a trusted issuer, the WS-Addressing specification leaves it to the receiver to decide whether to honour it, so Axis2 now declines by default. allowNonAnonymousResponseEndpoints is false; replies and faults travel back down the inbound connection only. Apache CXF made the same choice in org.apache.cxf.ws.addressing.decoupled.enabled.
Deployments that genuinely use decoupled responses — the separate-listener “Dual” clients, or a third-party callback endpoint — set it to true, and should also set httpFrontendHostUrl so the generated reply address is the real external URL rather than the local one. With the feature enabled:
allowedResponseEndpointSchemes permits HTTPS only. Widen it to name a transport actually used for replies.blockPrivateNetworkResponseEndpoints additionally refuses loopback and private ranges; it is off by default because a callback inside the same private network is how most decoupled deployments are wired.[::ffff:169.254.169.254]) is refused as the address it reaches rather than as a separate spelling. IPv6 unique-local (fc00::/7) is covered explicitly, since InetAddress.isSiteLocalAddress answers only for the deprecated fec0::/10.responseEndpointResolveTimeoutMillis) and runs on a capped pool, so a slow resolver cannot tie up request threads.Known limitation: the destination is resolved once to check it and again to connect, so a hostile DNS server could answer differently the second time. Closing that requires connecting to a pinned address, which the transport does not currently support. Operators in cloud environments should pair these settings with network egress controls.
Request body ceilings (2.0.2): The multipart/form-data and application/x-www-form-urlencoded builders read the transport stream directly, so a servlet container's post-size limit never sees the body. multipartMaxRequestSize and multipartMaxFileSize (100 MB) and formUrlEncodedMaxRequestSize (2 MB) bound them; -1 restores the previous unbounded behaviour, and either may be set per service. Multipart temp files are now deleted rather than accumulating: form-field parts as soon as their text is read, file parts once the item backing the DataHandler is unreachable.
Both ceilings are enforced against bytes actually read, not against a declared Content-Length, so a chunked request body is bounded on the same terms as a declared one. This is worth stating because the reverse is the easy mistake: a limit that screens the header before the read is no limit at all for Transfer-Encoding: chunked, which declares no length. The form-urlencoded builder wraps the stream in BoundedInputStream; the multipart path relies on commons-fileupload2, which pairs its Content-Length fast path with a streaming guard.
OpenAPI and Swagger UI output (2.0.2): Request-controlled values are validated and encoded for the context they are written into, the served page carries a Content-Security-Policy with a per-response script nonce, and the published servers[].url is relative — resolved by the client against wherever it fetched the document — rather than derived from the request Host. openapi.serverBaseUrl pins an absolute URL where a deployment needs one.
Uniform metadata exposure (2.0.2): exposeServiceMetadata is now honoured by every anonymous metadata route: the ?wsdl, ?wsdl2 and ?xsd queries as before, plus the .xsd/.wsdl file routes on both the servlet and standalone HTTP paths, the named-WSDL route, and the OpenAPI/Swagger/MCP generators. A service with exposure disabled is skipped rather than refused, so it stays indistinguishable from one that is not deployed.
Report vulnerabilities to: security@apache.org
Follow the Apache Security Policy. All confirmed issues go through coordinated disclosure with CVE assignment.