You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2021/12/11 23:06:11 UTC

[logging-log4j2] branch master updated: LOG4J2-3208 - Disable JNDI by default

This is an automated email from the ASF dual-hosted git repository.

rgoers pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/master by this push:
     new 4456909  LOG4J2-3208 - Disable JNDI by default
4456909 is described below

commit 44569090f1cf1e92c711fb96dfd18cd7dccc72ea
Author: Ralph Goers <rg...@apache.org>
AuthorDate: Sat Dec 11 16:05:58 2021 -0700

    LOG4J2-3208 - Disable JNDI by default
---
 .../logging/log4j/core/lookup/Interpolator.java    | 19 +++++---
 .../apache/logging/log4j/core/net/JndiManager.java | 52 +++++++++++++++-------
 .../log4j/core/selector/JndiContextSelector.java   |  6 +++
 .../routing/RoutingAppenderWithJndiTest.java       |  8 +++-
 .../log4j/core/lookup/InterpolatorTest.java        |  2 +
 ...LookupTest.java => JndiDisabledLookupTest.java} | 26 +++--------
 .../logging/log4j/core/lookup/JndiLookupTest.java  |  6 +++
 .../core/lookup/JndiRestrictedLookupTest.java      |  1 +
 .../logging/log4j/jms/appender/JmsManager.java     | 13 ++++--
 .../log4j/jms/appender/JmsAppenderTest.java        |  6 +++
 src/changes/changes.xml                            |  5 ++-
 src/site/asciidoc/manual/appenders.adoc            |  4 ++
 src/site/asciidoc/manual/configuration.adoc        | 26 +++++++++++
 src/site/asciidoc/manual/logsep.adoc               |  4 ++
 src/site/asciidoc/manual/lookups.adoc              |  4 ++
 src/site/asciidoc/security.adoc                    |  2 +-
 16 files changed, 135 insertions(+), 49 deletions(-)

diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
index cea22d6..ff10705 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
@@ -24,6 +24,7 @@ import java.util.Map;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.ConfigurationAware;
+import org.apache.logging.log4j.core.net.JndiManager;
 import org.apache.logging.log4j.core.util.Loader;
 import org.apache.logging.log4j.util.ReflectionUtil;
 import org.apache.logging.log4j.plugins.util.PluginManager;
@@ -77,7 +78,9 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
         for (final Map.Entry<String, PluginType<?>> entry : plugins.entrySet()) {
             try {
                 final Class<? extends StrLookup> clazz = entry.getValue().getPluginClass().asSubclass(StrLookup.class);
-                strLookupMap.put(entry.getKey().toLowerCase(), ReflectionUtil.instantiate(clazz));
+                if (!clazz.getName().equals(JndiLookup.class.getName()) || JndiManager.isIsJndiEnabled()) {
+                    strLookupMap.put(entry.getKey().toLowerCase(), ReflectionUtil.instantiate(clazz));
+                }
             } catch (final Throwable t) {
                 handleError(entry.getKey(), t);
             }
@@ -107,12 +110,14 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
         strLookupMap.put("lower", new LowerLookup());
         strLookupMap.put("upper", new UpperLookup());
         // JNDI
-        try {
-            // [LOG4J2-703] We might be on Android
-            strLookupMap.put(LOOKUP_KEY_JNDI,
-                Loader.newCheckedInstanceOf("org.apache.logging.log4j.core.lookup.JndiLookup", StrLookup.class));
-        } catch (final LinkageError | Exception e) {
-            handleError(LOOKUP_KEY_JNDI, e);
+        if (JndiManager.isIsJndiEnabled()) {
+            try {
+                // [LOG4J2-703] We might be on Android
+                strLookupMap.put(LOOKUP_KEY_JNDI,
+                        Loader.newCheckedInstanceOf("org.apache.logging.log4j.core.lookup.JndiLookup", StrLookup.class));
+            } catch (final LinkageError | Exception e) {
+                handleError(LOOKUP_KEY_JNDI, e);
+            }
         }
         // JMX input args
         try {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/JndiManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/JndiManager.java
index 9f524e5..718a203 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/JndiManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/JndiManager.java
@@ -73,6 +73,10 @@ public class JndiManager extends AbstractManager {
 
     private final DirContext context;
 
+    public static boolean isIsJndiEnabled() {
+        return PropertiesUtil.getProperties().getBooleanProperty("log4j2.enableJndi", false);
+    }
+
     private JndiManager(final String name, final DirContext context, final List<String> allowedHosts,
             final List<String> allowedClasses, final List<String> allowedProtocols) {
         super(null, name);
@@ -82,6 +86,14 @@ public class JndiManager extends AbstractManager {
         this.allowedProtocols = allowedProtocols;
     }
 
+    private JndiManager(final String name) {
+        super(null, name);
+        this.context = null;
+        this.allowedProtocols = null;
+        this.allowedClasses = null;
+        this.allowedHosts = null;
+    }
+
     /**
      * Gets the default JndiManager using the default {@link javax.naming.InitialContext}.
      *
@@ -194,6 +206,9 @@ public class JndiManager extends AbstractManager {
 
     @Override
     protected boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
+        if (context != null) {
+            return JndiCloser.closeSilently(this.context);
+        }
         return JndiCloser.closeSilently(this.context);
     }
 
@@ -207,6 +222,9 @@ public class JndiManager extends AbstractManager {
      */
     @SuppressWarnings("unchecked")
     public synchronized <T> T lookup(final String name) throws NamingException {
+        if (context == null) {
+            return null;
+        }
         try {
             URI uri = new URI(name);
             if (uri.getScheme() != null) {
@@ -262,21 +280,25 @@ public class JndiManager extends AbstractManager {
 
         @Override
         public JndiManager createManager(final String name, final Properties data) {
-            String hosts = data != null ? data.getProperty(ALLOWED_HOSTS) : null;
-            String classes = data != null ? data.getProperty(ALLOWED_CLASSES) : null;
-            String protocols = data != null ? data.getProperty(ALLOWED_PROTOCOLS) : null;
-            List<String> allowedHosts = new ArrayList<>();
-            List<String> allowedClasses = new ArrayList<>();
-            List<String> allowedProtocols = new ArrayList<>();
-            addAll(hosts, allowedHosts, permanentAllowedHosts, ALLOWED_HOSTS, data);
-            addAll(classes, allowedClasses, permanentAllowedClasses, ALLOWED_CLASSES, data);
-            addAll(protocols, allowedProtocols, permanentAllowedProtocols, ALLOWED_PROTOCOLS, data);
-            try {
-                return new JndiManager(name, new InitialDirContext(data), allowedHosts, allowedClasses,
-                        allowedProtocols);
-            } catch (final NamingException e) {
-                LOGGER.error("Error creating JNDI InitialContext.", e);
-                return null;
+            if (isIsJndiEnabled()) {
+                String hosts = data != null ? data.getProperty(ALLOWED_HOSTS) : null;
+                String classes = data != null ? data.getProperty(ALLOWED_CLASSES) : null;
+                String protocols = data != null ? data.getProperty(ALLOWED_PROTOCOLS) : null;
+                List<String> allowedHosts = new ArrayList<>();
+                List<String> allowedClasses = new ArrayList<>();
+                List<String> allowedProtocols = new ArrayList<>();
+                addAll(hosts, allowedHosts, permanentAllowedHosts, ALLOWED_HOSTS, data);
+                addAll(classes, allowedClasses, permanentAllowedClasses, ALLOWED_CLASSES, data);
+                addAll(protocols, allowedProtocols, permanentAllowedProtocols, ALLOWED_PROTOCOLS, data);
+                try {
+                    return new JndiManager(name, new InitialDirContext(data), allowedHosts, allowedClasses,
+                            allowedProtocols);
+                } catch (final NamingException e) {
+                    LOGGER.error("Error creating JNDI InitialContext.", e);
+                    return null;
+                }
+            } else {
+                return new JndiManager(name);
             }
         }
 
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/JndiContextSelector.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/JndiContextSelector.java
index fef98cb..0ee87e1 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/JndiContextSelector.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/JndiContextSelector.java
@@ -93,6 +93,12 @@ public class JndiContextSelector implements NamedContextSelector {
 
     private static final StatusLogger LOGGER = StatusLogger.getLogger();
 
+    public JndiContextSelector() {
+        if (!JndiManager.isIsJndiEnabled()) {
+            throw new IllegalStateException("JNDI must be enabled by setting log4j2.enableJndi=true");
+        }
+    }
+
     @Override
     public void shutdown(final String fqcn, final ClassLoader loader, final boolean currentContext, final boolean allContexts) {
         LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/routing/RoutingAppenderWithJndiTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/routing/RoutingAppenderWithJndiTest.java
index 9773c36..8d8b305 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/routing/RoutingAppenderWithJndiTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/routing/RoutingAppenderWithJndiTest.java
@@ -18,6 +18,7 @@ package org.apache.logging.log4j.core.appender.routing;
 
 import java.io.File;
 import java.util.Collections;
+import java.util.Map;
 import javax.naming.Context;
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
@@ -47,9 +48,14 @@ public class RoutingAppenderWithJndiTest {
     public static LoggerContextRule loggerContextRule = new LoggerContextRule("log4j-routing-by-jndi.xml");
 
     @ClassRule
-    public static RuleChain rules = RuleChain.outerRule(new JndiRule(Collections.<String, Object>emptyMap()))
+    public static RuleChain rules = RuleChain.outerRule(new JndiRule(initBindings()))
         .around(loggerContextRule);
 
+    private static Map<String, Object> initBindings() {
+        System.setProperty("log4j2.enableJndi", "true");
+        return Collections.emptyMap();
+    }
+
     @Before
     public void before() throws NamingException {
         listAppender1 = RoutingAppenderWithJndiTest.loggerContextRule.getListAppender("List1");
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/InterpolatorTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/InterpolatorTest.java
index 2cf7c19..3f5de41 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/InterpolatorTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/InterpolatorTest.java
@@ -48,12 +48,14 @@ public class InterpolatorTest {
         protected void before() throws Throwable {
             System.setProperty(TESTKEY, TESTVAL);
             System.setProperty(TESTKEY2, TESTVAL);
+            System.setProperty("log4j2.enableJndi", "true");
         }
 
         @Override
         protected void after() {
             System.clearProperty(TESTKEY);
             System.clearProperty(TESTKEY2);
+            System.clearProperty("log4j2.enableJndi");
         }
     }).around(new JndiRule(
         JndiLookup.CONTAINER_JNDI_RESOURCE_PATH_PREFIX + TEST_CONTEXT_RESOURCE_NAME, TEST_CONTEXT_NAME));
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiLookupTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiDisabledLookupTest.java
similarity index 71%
copy from log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiLookupTest.java
copy to log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiDisabledLookupTest.java
index 35b6c26..365d7d8 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiLookupTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiDisabledLookupTest.java
@@ -25,12 +25,14 @@ import org.apache.logging.log4j.core.test.junit.JndiRule;
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertNull;
 
 /**
- * JndiLookupTest
+ * JndiDisabledLookupTest
+ *
+ * Verifies the Lookups are disabled without the log4j2.enableJndi property set to true.
  */
-public class JndiLookupTest {
+public class JndiDisabledLookupTest {
 
     private static final String TEST_CONTEXT_RESOURCE_NAME = "logging/context-name";
     private static final String TEST_CONTEXT_NAME = "app-1";
@@ -55,22 +57,6 @@ public class JndiLookupTest {
         final StrLookup lookup = new JndiLookup();
 
         String contextName = lookup.lookup(TEST_CONTEXT_RESOURCE_NAME);
-        assertEquals(TEST_CONTEXT_NAME, contextName);
-
-        contextName = lookup.lookup(JndiLookup.CONTAINER_JNDI_RESOURCE_PATH_PREFIX + TEST_CONTEXT_RESOURCE_NAME);
-        assertEquals(TEST_CONTEXT_NAME, contextName);
-
-        final String nonExistingResource = lookup.lookup("logging/non-existing-resource");
-        assertNull(nonExistingResource);
-    }
-
-    @Test
-    public void testNonStringLookup() throws Exception {
-        // LOG4J2-1310
-        final StrLookup lookup = new JndiLookup();
-        final String integralValue = lookup.lookup(TEST_INTEGRAL_NAME);
-        assertEquals(String.valueOf(TEST_INTEGRAL_VALUE), integralValue);
-        final String collectionValue = lookup.lookup(TEST_STRINGS_NAME);
-        assertEquals(String.valueOf(TEST_STRINGS_COLLECTION), collectionValue);
+        assertNull(contextName);
     }
 }
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiLookupTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiLookupTest.java
index 35b6c26..bc81613 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiLookupTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiLookupTest.java
@@ -22,6 +22,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.logging.log4j.core.test.junit.JndiRule;
+import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -42,6 +43,11 @@ public class JndiLookupTest {
     @Rule
     public JndiRule jndiRule = new JndiRule(createBindings());
 
+    @BeforeClass
+    public static void beforeClass() {
+        System.setProperty("log4j2.enableJndi", "true");
+    }
+
     private Map<String, Object> createBindings() {
         final Map<String, Object> map = new HashMap<>();
         map.put(JndiLookup.CONTAINER_JNDI_RESOURCE_PATH_PREFIX + TEST_CONTEXT_RESOURCE_NAME, TEST_CONTEXT_NAME);
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiRestrictedLookupTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiRestrictedLookupTest.java
index b0023b2..2765afe 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiRestrictedLookupTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiRestrictedLookupTest.java
@@ -54,6 +54,7 @@ public class JndiRestrictedLookupTest {
     public static void beforeClass() {
         System.setProperty("log4j2.allowedLdapClasses", Level.class.getName());
         System.setProperty("log4j2.allowedJndiProtocols", "dns");
+        System.setProperty("log4j2.enableJndi", "true");
     }
 
     @Test
diff --git a/log4j-jms/src/main/java/org/apache/logging/log4j/jms/appender/JmsManager.java b/log4j-jms/src/main/java/org/apache/logging/log4j/jms/appender/JmsManager.java
index 291fd7d..dae562d 100644
--- a/log4j-jms/src/main/java/org/apache/logging/log4j/jms/appender/JmsManager.java
+++ b/log4j-jms/src/main/java/org/apache/logging/log4j/jms/appender/JmsManager.java
@@ -125,10 +125,15 @@ public class JmsManager extends AbstractManager {
 
         @Override
         public JmsManager createManager(final String name, final JmsManagerConfiguration data) {
-            try {
-                return new JmsManager(name, data);
-            } catch (final Exception e) {
-                logger().error("Error creating JmsManager using JmsManagerConfiguration [{}]", data, e);
+            if (JndiManager.isIsJndiEnabled()) {
+                try {
+                    return new JmsManager(name, data);
+                } catch (final Exception e) {
+                    logger().error("Error creating JmsManager using JmsManagerConfiguration [{}]", data, e);
+                    return null;
+                }
+            } else {
+                logger().error("JNDI has not been enabled. The log4j2.enableJndi property must be set to true");
                 return null;
             }
         }
diff --git a/log4j-jms/src/test/java/org/apache/logging/log4j/jms/appender/JmsAppenderTest.java b/log4j-jms/src/test/java/org/apache/logging/log4j/jms/appender/JmsAppenderTest.java
index 05a56ad..a878640 100644
--- a/log4j-jms/src/test/java/org/apache/logging/log4j/jms/appender/JmsAppenderTest.java
+++ b/log4j-jms/src/test/java/org/apache/logging/log4j/jms/appender/JmsAppenderTest.java
@@ -49,6 +49,7 @@ import org.apache.logging.log4j.message.Message;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.message.StringMapMessage;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
@@ -83,6 +84,11 @@ public class JmsAppenderTest {
     @Rule
     public RuleChain rules = RuleChain.outerRule(jndiRule).around(ctx);
 
+    @BeforeClass
+    public static void beforeClass() throws Exception {
+        System.setProperty("log4j2.enableJndi", "true");
+    }
+
     public JmsAppenderTest() throws Exception {
         // this needs to set up before LoggerContextRule
         given(connectionFactory.createConnection()).willReturn(connection);
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index ef63c65..3327e35 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -168,7 +168,10 @@
 		    Fixes incorrect constructor call in LocalizedMessageFactory.
       </action>
     </release>
-    <release version="2.15.1" date="2021-12-XX" description="GA Release 2.15.0">
+    <release version="2.15.1" date="2021-12-XX" description="GA Release 2.15.1">
+      <action issue="LOG4J2-3208" dev="rgoers" type="fix">
+        Disable JNDI by default. Require log4j2.enableJndi to be set to true to allow JNDI.
+      </action>
     </release>
     <release version="2.15.0" date="2021-12-06" description="GA Release 2.15.0">
       <!-- ADDS -->
diff --git a/src/site/asciidoc/manual/appenders.adoc b/src/site/asciidoc/manual/appenders.adoc
index 4b20bb3..c657537 100644
--- a/src/site/asciidoc/manual/appenders.adoc
+++ b/src/site/asciidoc/manual/appenders.adoc
@@ -1259,6 +1259,10 @@ As of Log4j 2.11.0, JPA support has moved from the existing module
 
 The JMS Appender sends the formatted log event to a JMS Destination.
 
+The JMS Appender requires JNDI support so as of release 2.15.1 this appender will not function unless
+`log4j2.enableJndi=true` is configured as a system property or environment variable. See the
+link:./configuration.html#enableJndi[log4j2.enableJndi] system property.
+
 Note that in Log4j 2.0, this appender was split into a JMSQueueAppender
 and a JMSTopicAppender. Starting in Log4j 2.1, these appenders were
 combined into the JMS Appender which makes no distinction between queues
diff --git a/src/site/asciidoc/manual/configuration.adoc b/src/site/asciidoc/manual/configuration.adoc
index 4ec763a..7f513d3 100644
--- a/src/site/asciidoc/manual/configuration.adoc
+++ b/src/site/asciidoc/manual/configuration.adoc
@@ -2073,6 +2073,32 @@ context class loader before falling back to the default class loader.
 |If `true`, classes and configuration are only loaded with the default context class loader.
 Otherwise, log4j also uses the log4j classloader, parent classloaders and the system classloader.
 
+|[[enableJndi]]log4j2.enableJndi +
+([[log4j.enableJndi]]log4j.enableJndi)
+|LOG4J_ENABLE_JNDI
+|false
+| When true, Log4j components that use JNDI are enabled. When false, the default, they are disabled.
+
+|[[allowedLdapClasses]]log4j2.allowedLdapClasses +
+([[log4j.allowedLdapClasses]]log4j.allowedLdapClasses)
+|LOG4J_ALLOWED_LDAP_CLASSES
+|&nbsp;
+| System property that specifies fully qualified class names that may be accessed by LDAP. The classes
+must implement Serializable. By default only Java primative classes are allowed.
+
+|[[allowedLdapHosts]]log4j2.allowedLdapHosts +
+([[log4j.allowedLdapHosts]]log4j.allowedLdapHosts)
+|LOG4J_ALLOWED_LDAP_HOSTS
+|&nbsp;
+| System property that adds host names or ip addresses that may be access by LDAP. By default it only allows
+the local host names and ip addresses.
+
+|[[allowedJndiProtocols]]log4j2.allowedJndiProtocols +
+([[log4j.allowedJndiProtocols]]log4j.allowedJndiProtocols)
+|LOG4J_ALLOWED_JNDI_PROTOCOLS
+|&nbsp;
+| System property that adds protocol names that JNDI will allow. By default it only allows java, ldap, and ldaps.
+
 |[[uuidSequence]]log4j2.uuidSequence +
 ([[org.apache.logging.log4j.uuidSequence]]org.apache.logging.log4j.uuidSequence)
 |LOG4J_UUID_SEQUENCE
diff --git a/src/site/asciidoc/manual/logsep.adoc b/src/site/asciidoc/manual/logsep.adoc
index ae52bc3..94c1687 100644
--- a/src/site/asciidoc/manual/logsep.adoc
+++ b/src/site/asciidoc/manual/logsep.adoc
@@ -116,6 +116,10 @@ cause the container to use JNDI to locate each web application's
 context parameter to true and also set the `log4jContextName` and
 `log4jConfiguration` context parameters.
 
+The `JndiContextSelector` will not work unless `log4j2.enableJndi=true` is set as a system property
+or environment variable. See the
+link:./configuration.html#enableJndi[log4j2.enableJndi] system property.
+
 The exact method for setting system properties depends on the container.
 For Tomcat, edit `$CATALINA_HOME/conf/catalina.properties`. Consult the
 documentation for other web containers.
diff --git a/src/site/asciidoc/manual/lookups.adoc b/src/site/asciidoc/manual/lookups.adoc
index 986ac65..8408943 100644
--- a/src/site/asciidoc/manual/lookups.adoc
+++ b/src/site/asciidoc/manual/lookups.adoc
@@ -267,6 +267,10 @@ For example:
 [#JndiLookup]
 == JNDI Lookup
 
+As of Log4j 2.15.1 JNDI operations require that `log4j2.enableJndi=tru`e be set as a system property or the
+corresponding environment variable for this lookup to function. See the
+link:./configuration.html#enableJndi[log4j2.enableJndi] system property.
+
 The JndiLookup allows variables to be retrieved via JNDI. By default the
 key will be prefixed with java:comp/env/, however if the key contains a
 ":" no prefix will be added.
diff --git a/src/site/asciidoc/security.adoc b/src/site/asciidoc/security.adoc
index 7a6d022..1276615 100644
--- a/src/site/asciidoc/security.adoc
+++ b/src/site/asciidoc/security.adoc
@@ -63,7 +63,7 @@ substitution is enabled. From log4j 2.15.0, this behavior has been disabled by d
 Mitigation: In releases &gt;= 2.10, this behavior can be mitigated by setting either the system property
 `log4j2.formatMsgNoLookups` or the environment variable `LOG4J_FORMAT_MSG_NO_LOOKUPS` to `true`.
 For releases from 2.7 through 2.14.1 all PatternLayout patterns can be modified to specify the message converter as
-`%m{nnolookups}` instead of just `%m`.
+`%m{nolookups}` instead of just `%m`.
 For releases from 2.0-beta9 to 2.7, the only mitigation is to remove the `JndiLookup` class from the classpath:
 `zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class`.