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/09/18 15:21:36 UTC
(unomi) 02/04: Keep personalization fallback when mixed contents include a script value.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch bound-diagnostic-and-script-caches
in repository https://gitbox.apache.org/repos/asf/unomi.git
commit cdf479c2ebb9868964b13adb842e2132d47f17ae
Author: Serge Huber <sh...@apache.org>
AuthorDate: Tue Sep 8 21:01:08 2026 +0200
Keep personalization fallback when mixed contents include a script value.
Add an integration test that posts a mixed personalizations payload and expects the safe variant.
---
.../org/apache/unomi/itests/ContextServletIT.java | 24 ++++++++++++++++
.../mvel-payload-personalization-mixed.json | 32 ++++++++++++++++++++++
2 files changed, 56 insertions(+)
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 247460e26..1e1bc00a8 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ContextServletIT.java
@@ -1137,6 +1137,30 @@ public class ContextServletIT extends BaseIT {
exists -> exists == Boolean.FALSE, DEFAULT_TRYING_TIMEOUT, DEFAULT_SHOULDBETRUE_TRIES);
}
+ @Test
+ public void testPersonalizationDropsScriptContentAndKeepsFallback() throws Exception {
+ File vulnFile = new File("target/vuln-file-personalization-mixed.txt");
+ if (vulnFile.exists()) {
+ vulnFile.delete();
+ }
+ String vulnFileCanonicalPath = vulnFile.getCanonicalPath().replace("\\", "\\\\");
+
+ 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-personalization-mixed.json", parameters),
+ ContentType.APPLICATION_JSON));
+ RequestResponse response = executeContextJSONRequest(request, TEST_SESSION_ID);
+
+ assertEquals("Invalid response code", 200, response.getStatusCode());
+ List<String> variants = response.getContextResponse().getPersonalizations().get("mixed-sanitize");
+ assertNotNull(variants);
+ assertEquals(Collections.singletonList("safe-fallback"), variants);
+ shouldBeTrueUntilEnd("Vulnerability successfully executed ! File created at " + vulnFileCanonicalPath, vulnFile::exists,
+ exists -> exists == Boolean.FALSE, DEFAULT_TRYING_TIMEOUT, DEFAULT_SHOULDBETRUE_TRIES);
+ }
+
@Test
public void testPersonalization() throws Exception {
diff --git a/itests/src/test/resources/security/mvel-payload-personalization-mixed.json b/itests/src/test/resources/security/mvel-payload-personalization-mixed.json
new file mode 100644
index 000000000..4d11b1ae0
--- /dev/null
+++ b/itests/src/test/resources/security/mvel-payload-personalization-mixed.json
@@ -0,0 +1,32 @@
+{
+ "personalizations": [
+ {
+ "id": "mixed-sanitize",
+ "strategy": "matching-first",
+ "strategyOptions": {
+ "fallback": "safe-fallback"
+ },
+ "contents": [
+ {
+ "id": "injected",
+ "filters": [
+ {
+ "condition": {
+ "type": "profilePropertyCondition",
+ "parameterValues": {
+ "propertyName": "firstName",
+ "comparisonOperator": "equals",
+ "propertyValue": "script::Runtime r = Runtime.getRuntime(); r.exec(\"touch ###VULN_FILE_PATH###\");"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "id": "safe-fallback"
+ }
+ ]
+ }
+ ],
+ "sessionId": "demo-session-id"
+}