How RASP Protects Against the XXE Vulnerability CVE-2025-66516

1.Overview
A critical security flaw has been disclosed in Apache Tika that could result in an XML external entity (XXE) injection attack.
The vulnerability, tracked as CVE-2025-66516, is rated 10.0 on the CVSS scoring scale, indicating maximum severity.
“Critical XXE in Apache Tika tika-core (1.13-3.2.1), tika-pdf-module (2.0.0-3.2.1) and tika-parsers (1.13-1.28.5) modules on all platforms allows an attacker to carry out XML External Entity injection via a crafted XFA file inside of a PDF,” according to an advisory for the vulnerability.
It affects the following Maven packages –
- org.apache.tika:tika-core >= 1.13, <= 3.2.1 (Patched in version 3.2.2)
- org.apache.tika:tika-parser-pdf-module >= 2.0.0, <= 3.2.1 (Patched in version 3.2.2)
- org.apache.tika:tika-parsers >= 1.13, < 2.0.0 (Patched in version 2.0.0)
XXE injection refers to a web security vulnerability that allows an attacker to interfere with an application’s processing of XML data. This, in turn, makes it possible to access files on the application server file system and, in some cases, even, achieve remote code execution.
package com.rasp.example.cve202566516;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.pdf.PDFParser;
import org.apache.tika.sax.BodyContentHandler;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.xml.sax.ContentHandler;
import java.io.InputStream;
@RestController
@RequestMapping("/xxe")
public class XxeController {
@GetMapping("/tika")
public ResponseEntity<String> readPDF() throws Exception {
InputStream is = getClass().getClassLoader().getResourceAsStream("xfa_passwd.pdf");
ContentHandler handler = new BodyContentHandler();
Metadata metadata = new Metadata();
PDFParser pdfParser = new PDFParser();
ParseContext context = new ParseContext();
pdfParser.parse(is, handler, metadata, context);
System.out.println("pdf content: " + handler.toString());
return ResponseEntity.ok(handler.toString());
}
}
xfa_passwd.pdf is from https://github.com/mgthuramoemyint/POC-CVE-2025-54988
when http://localhost:8080/xxe/tika

2. Vulnerability Detection
when we use RASP for web application:

RASP Intercepted Stack Characteristics:
com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java)
com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:1240)
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEntityReference(XMLDocumentFragmentScannerImpl.java:1908)
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3061)
com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:553)
org.apache.tika.parser.pdf.XFAExtractor.loadData(XFAExtractor.java:220)
org.apache.tika.parser.pdf.XFAExtractor.extract(XFAExtractor.java:100)
org.apache.tika.parser.pdf.AbstractPDF2XHTML.extractAcroForm(AbstractPDF2XHTML.java:1184)
org.apache.tika.parser.pdf.AbstractPDF2XHTML.endDocument(AbstractPDF2XHTML.java:1009)
org.apache.pdfbox.text.PDFTextStripper.writeText(PDFTextStripper.java:239)
org.apache.tika.parser.pdf.PDF2XHTML.process(PDF2XHTML.java:108)
org.apache.tika.parser.pdf.PDFParser.parse(PDFParser.java:219)
com.sankuai.rasp.cve202566516.XxeController.readPDF(XxeController.java:26)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
javax.servlet.http.HttpServlet.service(HttpServlet.java:529)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
javax.servlet.http.HttpServlet.service(HttpServlet.java:623)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:928)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1794)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:748)

3. XXE Hooks for RASP
Although there are numerous middleware for XML parsing, it suffices to hook the XML entity parsing section. For instance, both DOM4J and JAXP tools rely on Apache Xerces for XML entity parsing. The relevant hook points are summarized as follows:
- Apache Xerces
org.apache.xerces.impl.XMLEntityManager#startEntity(String, org.apache.xerces.xni.parser.XMLInputSource, boolean, boolean)

- Apache Xerces integrated in JDK
com.sun.org.apache.xerces.internal.impl.XMLEntityManager#startEntity(boolean, String, XMLInputSource, boolean, boolean)

As observed, the two hook points differ not only in their package names but also in their parameter lists.
- wstx in WebLogic Server
com.ctc.wstx.sr.StreamScanner#expandEntity(com.ctc.wstx.ent.EntityDecl, boolean)

4. XXE Vulnerability Detection Algorithm
The protocols exploitable for XXE vulnerabilities in Java are limited, and all supported protocols fall under the sun.net.www.protocol package. The protocols supported by JDK 8 and JDK 11 are as follows:
- JDK 11: jmod, jrt, mailto, file, ftp, http, https, jar;
- JDK 8: mailto, netdoc, file, ftp, http, https, jar;
It is sufficient to retrieve the protocol name, path, and host name of external entity resources and perform detection on each respectively. The parameter retrieval and detection methods are as follows:

