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