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

jacopoc pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 433dd85e0b Improved: Allow opting-out from the whitelist-restricted 
static models in freemarker (OFBIZ-13371)
433dd85e0b is described below

commit 433dd85e0bcf05412fd1d0fe7ed54bd0bbc65809
Author: Konstantinos Marinos <[email protected]>
AuthorDate: Mon Mar 16 08:24:47 2026 +0100

    Improved: Allow opting-out from the whitelist-restricted static models in 
freemarker (OFBIZ-13371)
    
    Improved: Allow the use of the whitelist restricted static Models in
    Freemarker to be globally switched off through the property
    freemarker.use-restricted-static-models in security.properties.
    
    [(OFBIZ-13371)](https://issues.apache.org/jira/browse/OFBIZ-13371)
    
    Explanation: Before this change all static method (shared
    by the "Static" variable) in Freemarker templates need to be explicitly
    whitelisted so they can be called.
    
    This change allows the whitelist to be turned off globally through a 
security property.
    
    ---------
    
    Co-authored-by: Konstantinos Marinos <[email protected]>
---
 .../ofbiz/base/util/template/FreeMarkerWorker.java | 45 +++++++++++++++++-----
 .../apache/ofbiz/entity/util/EntitySaxReader.java  |  2 +-
 framework/security/config/security.properties      |  4 ++
 3 files changed, 40 insertions(+), 11 deletions(-)

diff --git 
a/framework/base/src/main/java/org/apache/ofbiz/base/util/template/FreeMarkerWorker.java
 
b/framework/base/src/main/java/org/apache/ofbiz/base/util/template/FreeMarkerWorker.java
index 13bcb6e77c..d3594fc9ca 100644
--- 
a/framework/base/src/main/java/org/apache/ofbiz/base/util/template/FreeMarkerWorker.java
+++ 
b/framework/base/src/main/java/org/apache/ofbiz/base/util/template/FreeMarkerWorker.java
@@ -82,8 +82,8 @@ public final class FreeMarkerWorker {
     private static final UtilCache<String, Template> CACHED_TEMPLATES =
             UtilCache.createUtilCache("template.ftl.general", 0, 0, false);
     private static final BeansWrapper DEFAULT_OFBIZ_WRAPPER = new 
BeansWrapperBuilder(VERSION).build();
-    private static final TemplateHashModel DEFAULT_RESTRICTED_STATIC_MODELS =
-            
RestrictedStaticModels.fromConfig(DEFAULT_OFBIZ_WRAPPER.getStaticModels(), 
"freemarker-whitelist");
+    private static final TemplateHashModel DEFAULT_STATIC_MODELS =
+            getConfiguredStaticModel(getDefaultOfbizWrapper());
     private static final Configuration DEFAULT_OFBIZ_CONFIG = 
makeConfiguration(DEFAULT_OFBIZ_WRAPPER);
 
     public static BeansWrapper getDefaultOfbizWrapper() {
@@ -91,17 +91,20 @@ public final class FreeMarkerWorker {
     }
 
     /**
-     * Returns the whitelist-restricted {@link TemplateHashModel} that backs 
the
+     * Returns the configured {@link TemplateHashModel} that backs the
      * {@code Static} shared variable in every FreeMarker template.
      *
-     * <p>Use this instead of {@code 
getDefaultOfbizWrapper().getStaticModels()} whenever
-     * you need to expose the {@code Static} variable to a custom FreeMarker 
context, so
-     * that the same whitelist restrictions apply uniformly.
+     * <p>By default, the whitelist-restricted {@link RestrictedStaticModels} 
are returned.
+     * If you wish to override this behaviour, set {@code 
freemarker.use-restricted-static-models}
+     * in security.properties to {@code false}.
      *
-     * @return the {@link RestrictedStaticModels} instance for the default 
OFBiz wrapper
+     * <p>Use this whenever you need to expose the {@code Static} variable to 
a custom
+     * FreeMarker context, so that the same whitelist restrictions apply 
uniformly.
+     *
+     * @return the configured {@link TemplateHashModel} instance for the 
default OFBiz wrapper
      */
-    public static TemplateHashModel getRestrictedStaticModels() {
-        return DEFAULT_RESTRICTED_STATIC_MODELS;
+    public static TemplateHashModel getStaticModels() {
+        return DEFAULT_STATIC_MODELS;
     }
 
     public static Configuration newConfiguration() {
@@ -112,8 +115,8 @@ public final class FreeMarkerWorker {
         Configuration newConfig = newConfiguration();
 
         newConfig.setObjectWrapper(wrapper);
+        newConfig.setSharedVariable("Static", 
getConfiguredStaticModel(wrapper));
         TemplateHashModel rawStaticModels = wrapper.getStaticModels();
-        newConfig.setSharedVariable("Static", 
RestrictedStaticModels.fromConfig(rawStaticModels, "freemarker-whitelist"));
         try {
             newConfig.setSharedVariable("EntityQuery", 
rawStaticModels.get("org.apache.ofbiz.entity.util.EntityQuery"));
         } catch (TemplateModelException e) {
@@ -169,6 +172,28 @@ public final class FreeMarkerWorker {
         return newConfig;
     }
 
+    /**
+     * Return an unrestricted or a whitelist-restricted {@link 
TemplateHashModel}
+     * depending on the value of {@code 
freemarker.use-restricted-static-models} in
+     * security.properties.
+     *
+     * <p>If the wrapper is {@code null}, then the default OFBiz {@code 
BeansWrapper} is used.
+     *
+     * @param wrapper The current {@link BeansWrapper}
+     * @return the configured {@link RestrictedStaticModels} or
+     * {@link freemarker.ext.beans.StaticModels.StaticModels StaticModels}
+     */
+    private static TemplateHashModel getConfiguredStaticModel(BeansWrapper 
wrapper) {
+        TemplateHashModel staticModels = 
getDefaultOfbizWrapper().getStaticModels();
+        if (wrapper != null) {
+            staticModels = wrapper.getStaticModels();
+        }
+        if (UtilProperties.getPropertyAsBoolean("security", 
"freemarker.use-restricted-static-models", true)) {
+            staticModels = RestrictedStaticModels.fromConfig(staticModels, 
"freemarker-whitelist");
+        }
+        return staticModels;
+    }
+
     /**
      * Provides the sequence of existing {@code 
freemarkerTransforms.properties} files.
      * @return a stream of resource location.
diff --git 
a/framework/entity/src/main/java/org/apache/ofbiz/entity/util/EntitySaxReader.java
 
b/framework/entity/src/main/java/org/apache/ofbiz/entity/util/EntitySaxReader.java
index b3e357d7a1..1ae45cdd90 100644
--- 
a/framework/entity/src/main/java/org/apache/ofbiz/entity/util/EntitySaxReader.java
+++ 
b/framework/entity/src/main/java/org/apache/ofbiz/entity/util/EntitySaxReader.java
@@ -388,7 +388,7 @@ public class EntitySaxReader extends DefaultHandler {
                     NodeModel nodeModel = 
NodeModel.wrap(this.rootNodeForTemplate);
 
                     Map<String, Object> context = new HashMap<>();
-                    context.put("Static", 
FreeMarkerWorker.getRestrictedStaticModels());
+                    context.put("Static", FreeMarkerWorker.getStaticModels());
 
                     context.put("doc", nodeModel);
                     template.process(context, outWriter);
diff --git a/framework/security/config/security.properties 
b/framework/security/config/security.properties
index 8d5b7c7bc9..1a5cca5f2a 100644
--- a/framework/security/config/security.properties
+++ b/framework/security/config/security.properties
@@ -410,3 +410,7 @@ PolicyDirectives=default-src 'self'
 
 #-- Give the size of shortener path when the functionality to shorter the url 
is used
 path.shortener.size=10
+
+#-- Use this in combination with freemarker-whitelist.properties to restrict 
static method calls in freemarker templates.
+#-- If set to false, no static method calls are filtered.
+freemarker.use-restricted-static-models=true

Reply via email to