ESAPI / esapi-java-legacy

ESAPI (The OWASP Enterprise Security API) is a free, open source, web application security control library that makes it easier for programmers to write lower-risk applications.

Home Page:https://owasp.org/www-project-enterprise-security-api/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Esapi giving issue working with graal native image

kartik-kaushik opened this issue · comments

Describe the bug
Spring Boot 3 native image not working with ESAPI dependency

Sample
Via the Spring Initializer, create any project with:
spring-boot-starter-parent:3.0.2
spring-boot-starter-actuator

add below dependency
org.owasp.esapi : esapi : 2.4.0.0

add ESAPI.properties in resources folder
https://raw.githubusercontent.com/OWASP/EJSF/master/esapi_master_FULL/WebContent/ESAPI.properties


Create a controller class

@RestController
public class HelloworldController {

private Logger logger = LoggerFactory.getLogger(HelloworldController.class);

@GetMapping(value = "/check", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public String check() {
String value="Success";
if (value != null) {
Encoder encoder = ESAPI.encoder();
return encoder.canonicalize(value, false);
}
return value;

}

}

Check with /check endpoint. The application works normally, but with native image giving error:

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.owasp.esapi.errors.ConfigurationException: java.lang.ClassNotFoundException: org.owasp.esapi.reference.DefaultSecurityConfiguration SecurityConfiguration class (org.owasp.esapi.reference.DefaultSecurityConfiguration) must be in class path.] with root cause

java.lang.ClassNotFoundException: org.owasp.esapi.reference.DefaultSecurityConfiguration
at java.base@17.0.5/java.lang.Class.forName(DynamicHub.java:1132) ~[spring-ldaps:na]
at java.base@17.0.5/java.lang.Class.forName(DynamicHub.java:1105) ~[spring-ldaps:na]
at org.owasp.esapi.util.ObjFactory.loadClassByStringName(ObjFactory.java:158) ~[na:na]
at org.owasp.esapi.util.ObjFactory.make(ObjFactory.java:81) ~[na:na]
at org.owasp.esapi.ESAPI.securityConfiguration(ESAPI.java:185) ~[na:na]
at org.owasp.esapi.ESAPI.encoder(ESAPI.java:101) ~[na:na]
at com.example.springldaps.HelloworldController.health(HelloworldController.java:47) ~[spring-ldaps:na]
at java.base@17.0.5/java.lang.reflect.Method.invoke(Method.java:568) ~[spring-ldaps:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207) ~[spring-ldaps:6.0.4]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152) ~[spring-ldaps:6.0.4]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-ldaps:6.0.4]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884) ~[spring-ldaps:6.0.4]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-ldaps:6.0.4]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-ldaps:6.0.4]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1080) ~[spring-ldaps:6.0.4]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:973) ~[spring-ldaps:6.0.4]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011) ~[spring-ldaps:6.0.4]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-ldaps:6.0.4]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:705) ~[spring-ldaps:6.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-ldaps:6.0.4]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814) ~[spring-ldaps:6.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:223) ~[na:na]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[na:na]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[spring-ldaps:10.1.5]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[na:na]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-ldaps:6.0.4]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-ldaps:6.0.4]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[na:na]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-ldaps:6.0.4]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-ldaps:6.0.4]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[na:na]
at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:109) ~[spring-ldaps:6.0.4]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-ldaps:6.0.4]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[na:na]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-ldaps:6.0.4]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-ldaps:6.0.4]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[na:na]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177) ~[na:na]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[na:na]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[spring-ldaps:10.1.5]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119) ~[na:na]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[spring-ldaps:10.1.5]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[na:na]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[na:na]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400) ~[na:na]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[spring-ldaps:10.1.5]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:859) ~[na:na]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1734) ~[na:na]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[spring-ldaps:10.1.5]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[na:na]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[na:na]
at java.base@17.0.5/java.lang.Thread.run(Thread.java:833) ~[spring-ldaps:na]at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:775) ~[spring-ldaps:na]
at org.graalvm.nativeimage.builder/com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadS

Kindly help in resolution of the same. If not supported, is there any alternative or work around for now?

When you created this issue, you should have seen this note:

# NOTE: Ware aware the problems with ESAPI and Jakarta EE, so please do NOT create a new issue for that.
To follow the status of that, please see GitHub Discussion https://github.com/ESAPI/esapi-java-legacy/discussions/768.

That, in fact, is an explanation of what is going on here. Spring Boot 3.x and Spring framework 6.x started using jakarta.servlet package namespace for the Servlet API. ESAPI uses the Servlet API from the javax.servlet package namespace. See the referenced discussion in #768 for details.

That said, the workaround for you would be for you to use the Maven (or Gradle) Shade plugin to shade the esapi-version.jar and any other dependent jars that you are using and have it convert javax.servlet to jakarta.servlet. For now, that is the only know workaround if you wish to support ESAPI with a new version of Spring Boot or Spring Framework that only supports Jakarta EE. (The plus side of that is that you should be able to get that approach to work for any version of ESAPI and as well as for other libraries that are using javax.servlet package namespace. If we do come up with a solution for ESAPI, we will definitely not be back porting it to earlier ESAPI versions.)

Closing this as a duplicate of GitHub issue #767 which was converted to discussion #768.