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