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

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


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

commit a85ba0aded5ae6f81aeea95b7b8b95f471752226
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)
    
    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]>
    
    (cherry picked from commit 433dd85e0bcf05412fd1d0fe7ed54bd0bbc65809)
---
 .../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 1721029aeb..548e9dcf81 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 ae002db6a3..80a765792f 100644
--- a/framework/security/config/security.properties
+++ b/framework/security/config/security.properties
@@ -392,3 +392,7 @@ Content-Security-Policy=Content-Security-Policy-Report-Only
 
 #-- Define policy directives, see 
https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
 PolicyDirectives=default-src 'self'
+
+#-- 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