You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by sh...@apache.org on 2026/06/29 16:34:15 UTC

(unomi) branch unomi-3.0.x updated: UNOMI-945: Apply sanitized condition parameters and add list IT (#790)

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

sergehuber pushed a commit to branch unomi-3.0.x
in repository https://gitbox.apache.org/repos/asf/unomi.git


The following commit(s) were added to refs/heads/unomi-3.0.x by this push:
     new 1ba645448 UNOMI-945: Apply sanitized condition parameters and add list IT (#790)
1ba645448 is described below

commit 1ba6454484b1b347c70181869b4aac4ea3d1f53d
Author: Serge Huber <sh...@apache.org>
AuthorDate: Mon Jun 29 18:34:09 2026 +0200

    UNOMI-945: Apply sanitized condition parameters and add list IT (#790)
---
 .../org/apache/unomi/itests/ContextServletIT.java  | 20 +++++++++++++++++++
 .../test/resources/security/mvel-payload-list.json | 23 ++++++++++++++++++++++
 .../unomi/rest/endpoints/ContextJsonEndpoint.java  |  3 ++-
 3 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java b/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
index 7014ec66e..fa51b228b 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
@@ -491,6 +491,26 @@ public class ContextServletIT extends BaseIT {
                 exists -> exists == Boolean.FALSE, DEFAULT_TRYING_TIMEOUT, DEFAULT_TRYING_TRIES);
     }
 
+    @Test
+    public void testMVELVulnerabilityWithListPropertyValues() throws Exception {
+        File vulnFile = new File("target/vuln-file-list.txt");
+        if (vulnFile.exists()) {
+            vulnFile.delete();
+        }
+        String vulnFileCanonicalPath = vulnFile.getCanonicalPath();
+        vulnFileCanonicalPath = vulnFileCanonicalPath.replace("\\", "\\\\"); // this is required for Windows support
+
+        Map<String, String> parameters = new HashMap<>();
+        parameters.put("VULN_FILE_PATH", vulnFileCanonicalPath);
+        HttpPost request = new HttpPost(getFullUrl(CONTEXT_URL));
+        request.setEntity(
+                new StringEntity(getValidatedBundleJSON("security/mvel-payload-list.json", parameters), ContentType.APPLICATION_JSON));
+        TestUtils.executeContextJSONRequest(request);
+
+        shouldBeTrueUntilEnd("Vulnerability successfully executed ! File created at " + vulnFileCanonicalPath, vulnFile::exists,
+                exists -> exists == Boolean.FALSE, DEFAULT_TRYING_TIMEOUT, DEFAULT_TRYING_TRIES);
+    }
+
     @Test
     public void testPersonalization() throws Exception {
 
diff --git a/itests/src/test/resources/security/mvel-payload-list.json b/itests/src/test/resources/security/mvel-payload-list.json
new file mode 100644
index 000000000..bfc6ff8f8
--- /dev/null
+++ b/itests/src/test/resources/security/mvel-payload-list.json
@@ -0,0 +1,23 @@
+{
+  "filters": [
+    {
+      "id": "filter1",
+      "filters": [
+        {
+          "condition": {
+            "parameterValues": {
+              "propertyName": "firstName",
+              "comparisonOperator": "equals",
+              "propertyValues": [
+                "safe-value",
+                "script::Runtime r = Runtime.getRuntime(); r.exec(\"touch ###VULN_FILE_PATH###\");"
+              ]
+            },
+            "type": "profilePropertyCondition"
+          }
+        }
+      ]
+    }
+  ],
+  "sessionId": "demo-session-id"
+}
diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
index 099926c75..39eca1220 100644
--- a/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
@@ -331,11 +331,12 @@ public class ContextJsonEndpoint {
         for (Map.Entry<String, Object> parameterEntry : condition.getParameterValues().entrySet()) {
             Object sanitizedValue = sanitizeValue(parameterEntry.getValue());
             if (sanitizedValue != null) {
-                newParameterValues.put(parameterEntry.getKey(), parameterEntry.getValue());
+                newParameterValues.put(parameterEntry.getKey(), sanitizedValue);
             } else {
                 return null;
             }
         }
+        condition.setParameterValues(newParameterValues);
         return condition;
     }