jakartaee/jaf-api

MailcapCommandMap requires accessDeclaredMembers when Security Manager is enabled

yersan opened this issue · 0 comments

Describe the bug

As part of this commit MailcapCommandMap:620 was modified and now the invoker application requires accessDeclaredMembers permission when running under the SecurityManager. This permission is now required because the class that represents the mime type data content handler is being loaded by using:

cl.getDeclaredConstructor().newInstance()

Which will require the accessDeclaredMembers permission to load any available constructor regardless of the constructor's access level. However, this piece of code is only dealing with public constructors because the new instance is executed immediately without taking into account the constructor visibility.

To avoid breaking existing applications that are being moved to Jakarta 10, MailcapCommandMap:620 can be replaced with
cl.getConstructor().newInstance(); and get the same result without requiring this additional permission.

To Reproduce
Deploy a servlet that sends an email with the security manager enabled:

$ wildfly/bin/standalone.sh -secmgr

@WebServlet(value = "/mail")
public class MailServlet extends HttpServlet {
    @Resource(mappedName = "java:jboss/mail/Default")
    private Session mailSession;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        PrintWriter out = response.getWriter();
        try {
            MimeMessage m = new MimeMessage(mailSession);
            Address from = new InternetAddress("from@mydomain.com");
            Address[] to = new InternetAddress[]{new InternetAddress("to@mydomain.com")};
            m.setFrom(from);
            m.setRecipients(Message.RecipientType.TO, to);
            m.setSubject("Test Mail");
            m.setSentDate(new java.util.Date());
            m.setContent("Mail sent from WildFly", "text/plain");
            Transport.send(m);
            out.println("Mail sent!");
        } catch (jakarta.mail.MessagingException e) {
            e.printStackTrace();
            out.println("Error in Sending Mail: " + e);
        }
    }
}

The following is the error trace of the issue:

14:01:43,837 ERROR [io.undertow.request] (default task-1) UT005023: Exception handling request to /jakarta-mail-tester-1.0-SNAPSHOT/mail: java.security.AccessControlException: WFSM000001: Permission check failed (permission "("java.lang.RuntimePermission" "accessDeclaredMembers")" in code source "(vfs:/content/jakarta-mail-tester-1.0-SNAPSHOT.war/WEB-INF/classes <no signer certificates>)" of "ModuleClassLoader for Module "deployment.jakarta-mail-tester-1.0-SNAPSHOT.war" from Service Module Loader")
	at org.wildfly.security.elytron-base@2.0.0.Final//org.wildfly.security.manager.WildFlySecurityManager.checkPermission(WildFlySecurityManager.java:309)
	at org.wildfly.security.elytron-base@2.0.0.Final//org.wildfly.security.manager.WildFlySecurityManager.checkPermission(WildFlySecurityManager.java:201)
	at java.base/java.lang.Class.checkMemberAccess(Class.java:2847)
	at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2549)
	at jakarta.activation.api@2.1.1-SNAPSHOT-jbossorg-1//jakarta.activation.MailcapCommandMap.getDataContentHandler(MailcapCommandMap.java:620)
	at jakarta.activation.api@2.1.1-SNAPSHOT-jbossorg-1//jakarta.activation.MailcapCommandMap.createDataContentHandler(MailcapCommandMap.java:573)
	at jakarta.activation.api@2.1.1-SNAPSHOT-jbossorg-1//jakarta.activation.DataHandler.getDataContentHandler(DataHandler.java:591)
	at jakarta.activation.api@2.1.1-SNAPSHOT-jbossorg-1//jakarta.activation.DataHandler.writeTo(DataHandler.java:290)
	at jakarta.mail.api@2.1.1-SNAPSHOT-jbossorg-1//jakarta.mail.internet.MimeUtility.getEncoding(MimeUtility.java:316)
	at jakarta.mail.api@2.1.1-SNAPSHOT-jbossorg-1//jakarta.mail.internet.MimeBodyPart.updateHeaders(MimeBodyPart.java:1580)
	at jakarta.mail.api@2.1.1-SNAPSHOT-jbossorg-1//jakarta.mail.internet.MimeMessage.updateHeaders(MimeMessage.java:2265)
	at jakarta.mail.api@2.1.1-SNAPSHOT-jbossorg-1//jakarta.mail.internet.MimeMessage.saveChanges(MimeMessage.java:2225)
	at jakarta.mail.api@2.1.1-SNAPSHOT-jbossorg-1//jakarta.mail.Transport.send(Transport.java:99)
	at deployment.jakarta-mail-tester-1.0-SNAPSHOT.war//wildfly.demo.MailServlet.doGet(MailServlet.java:44)
	at jakarta.servlet.api@6.0.0//jakarta.servlet.http.HttpServlet.service(HttpServlet.java:527)
	at jakarta.servlet.api@6.0.0//jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
	at org.wildfly.security.elytron-web.undertow-server@3.0.0.Final//org.wildfly.elytron.web.undertow.server.ElytronRunAsHandler.lambda$handleRequest$1(ElytronRunAsHandler.java:68)
	at org.wildfly.security.elytron-base@2.0.0.Final//org.wildfly.security.auth.server.FlexibleIdentityAssociation.runAsFunctionEx(FlexibleIdentityAssociation.java:103)
	at org.wildfly.security.elytron-base@2.0.0.Final//org.wildfly.security.auth.server.Scoped.runAsFunctionEx(Scoped.java:161)
	at org.wildfly.security.elytron-base@2.0.0.Final//org.wildfly.security.auth.server.Scoped.runAs(Scoped.java:73)
	at org.wildfly.security.elytron-web.undertow-server@3.0.0.Final//org.wildfly.elytron.web.undertow.server.ElytronRunAsHandler.handleRequest(ElytronRunAsHandler.java:67)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
	at io.undertow.core@2.3.0.Beta1//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.core@2.3.0.Beta1//io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
	at io.undertow.core@2.3.0.Beta1//io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
	at org.wildfly.security.elytron-web.undertow-server-servlet@3.0.0.Final//org.wildfly.elytron.web.undertow.server.servlet.CleanUpHandler.handleRequest(CleanUpHandler.java:38)
	at io.undertow.core@2.3.0.Beta1//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at org.wildfly.extension.undertow@27.0.0.Final-SNAPSHOT//org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
	at io.undertow.core@2.3.0.Beta1//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at org.wildfly.extension.undertow@27.0.0.Final-SNAPSHOT//org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52)
	at io.undertow.core@2.3.0.Beta1//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:275)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:134)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:131)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
	at org.wildfly.extension.undertow@27.0.0.Final-SNAPSHOT//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1435)
	at org.wildfly.extension.undertow@27.0.0.Final-SNAPSHOT//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1435)
	at org.wildfly.extension.undertow@27.0.0.Final-SNAPSHOT//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1435)
	at org.wildfly.extension.undertow@27.0.0.Final-SNAPSHOT//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1435)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:255)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.ServletInitialHandler$1$1.run(ServletInitialHandler.java:106)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at io.undertow.servlet@2.3.0.Beta1//io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:103)
	at io.undertow.core@2.3.0.Beta1//io.undertow.server.Connectors.executeRootHandler(Connectors.java:387)
	at io.undertow.core@2.3.0.Beta1//io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:859)
	at org.jboss.threads@2.4.0.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
	at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990)
	at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
	at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
	at org.jboss.xnio@3.8.8.Final//org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1282)
	at java.base/java.lang.Thread.run(Thread.java:829)

Expected behavior
I wouldn't expect to have to add this permission to load an expected class that will handle the mime type.