From a4163e627bf89d0f2d359bba25bdd14cdfdb10c1 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 7 Sep 2026 15:23:24 -0600 Subject: [PATCH 1/5] Add JavaScript finding regression tests --- ...vascriptSecurityFindingRegressionTest.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java diff --git a/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java b/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java new file mode 100644 index 0000000000..435d468d57 --- /dev/null +++ b/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java @@ -0,0 +1,36 @@ +package com.bencodez.advancedcore.api.javascript; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +class JavascriptSecurityFindingRegressionTest { + + private static final String INJECTED_MARKER = "[Javascript=Bukkit.shutdown()]"; + + @Test + void displayNamePlaceholderCannotCreateExecutableJavascript() { + String rendered = renderPlaceholder("Welcome %displayname%", "%displayname%"); + + assertEquals("Welcome [Javascript =Bukkit.shutdown()]", rendered); + } + + @Test + void placeholderApiOutputCannotCreateExecutableJavascript() { + String rendered = renderPlaceholder("Reward: %papi_value%", "%papi_value%"); + + assertEquals("Reward: [Javascript =Bukkit.shutdown()]", rendered); + } + + @Test + void conditionalItemPlaceholderCannotCreateExecutableJavascript() { + String rendered = renderPlaceholder("Item lore: {conditional_value}", "{conditional_value}"); + + assertEquals("Item lore: [Javascript =Bukkit.shutdown()]", rendered); + } + + private String renderPlaceholder(String configuredText, String placeholder) { + return JavascriptTextTemplate.parse(configuredText) + .evaluate(text -> text.replace(placeholder, INJECTED_MARKER), script -> "executed"); + } +} From 694f5ea84e2e015bf59d841b0fc153b19c629ef8 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 7 Sep 2026 16:35:31 -0600 Subject: [PATCH 2/5] Exercise real placeholder pipelines --- ...vascriptSecurityFindingRegressionTest.java | 55 ++++++++++++++----- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java b/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java index 435d468d57..654b2b0dfa 100644 --- a/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java +++ b/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java @@ -1,8 +1,24 @@ package com.bencodez.advancedcore.api.javascript; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; + +import java.util.HashMap; +import java.util.UUID; import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.bukkit.entity.Player; + +import com.bencodez.advancedcore.AdvancedCorePlugin; +import com.bencodez.advancedcore.api.messages.PlaceholderUtils; + +import me.clip.placeholderapi.PlaceholderAPI; class JavascriptSecurityFindingRegressionTest { @@ -10,27 +26,38 @@ class JavascriptSecurityFindingRegressionTest { @Test void displayNamePlaceholderCannotCreateExecutableJavascript() { - String rendered = renderPlaceholder("Welcome %displayname%", "%displayname%"); - - assertEquals("Welcome [Javascript =Bukkit.shutdown()]", rendered); + Player player = mock(Player.class); + org.mockito.Mockito.when(player.getDisplayName()).thenReturn(INJECTED_MARKER); + org.mockito.Mockito.when(player.getName()).thenReturn("test-player"); + org.mockito.Mockito.when(player.getUniqueId()).thenReturn(UUID.fromString("00000000-0000-0000-0000-000000000001")); + AdvancedCorePlugin plugin = mock(AdvancedCorePlugin.class, RETURNS_DEEP_STUBS); + try (MockedStatic core = mockStatic(AdvancedCorePlugin.class); + MockedStatic papi = mockStatic(PlaceholderAPI.class)) { + core.when(AdvancedCorePlugin::getInstance).thenReturn(plugin); + org.mockito.Mockito.when(plugin.isPlaceHolderAPIEnabled()).thenReturn(true); + org.mockito.Mockito.when(plugin.getOptions().isJavascriptEngineEnabled()).thenReturn(true); + papi.when(() -> PlaceholderAPI.setPlaceholders(any(org.bukkit.OfflinePlayer.class), anyString())) + .thenAnswer(invocation -> ((String) invocation.getArgument(1)).replace("%displayname%", + player.getDisplayName())); + + assertEquals("Welcome [Javascript =Bukkit.shutdown()]", + PlaceholderUtils.replaceJavascript(player, "Welcome %displayname%")); + } } @Test void placeholderApiOutputCannotCreateExecutableJavascript() { - String rendered = renderPlaceholder("Reward: %papi_value%", "%papi_value%"); - - assertEquals("Reward: [Javascript =Bukkit.shutdown()]", rendered); + HashMap placeholders = new HashMap<>(); + placeholders.put("papi_value", INJECTED_MARKER); + assertEquals("Reward: [Javascript =Bukkit.shutdown()]", + PlaceholderUtils.parseText("Reward: %papi_value%", placeholders)); } @Test void conditionalItemPlaceholderCannotCreateExecutableJavascript() { - String rendered = renderPlaceholder("Item lore: {conditional_value}", "{conditional_value}"); - - assertEquals("Item lore: [Javascript =Bukkit.shutdown()]", rendered); - } - - private String renderPlaceholder(String configuredText, String placeholder) { - return JavascriptTextTemplate.parse(configuredText) - .evaluate(text -> text.replace(placeholder, INJECTED_MARKER), script -> "executed"); + HashMap placeholders = new HashMap<>(); + placeholders.put("conditional_value", INJECTED_MARKER); + String itemText = PlaceholderUtils.replacePlaceHolder("Item lore: {conditional_value}", placeholders); + assertEquals("Item lore: [Javascript =Bukkit.shutdown()]", PlaceholderUtils.replaceJavascript(itemText)); } } From 8aab62047b7ccc00b5b57f97a106738503badfb7 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 7 Sep 2026 16:52:46 -0600 Subject: [PATCH 3/5] Exercise ItemBuilder placeholder pipeline --- ...vascriptSecurityFindingRegressionTest.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java b/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java index 654b2b0dfa..bf24b79289 100644 --- a/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java +++ b/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java @@ -14,9 +14,12 @@ import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import com.bencodez.advancedcore.AdvancedCorePlugin; import com.bencodez.advancedcore.api.messages.PlaceholderUtils; +import com.bencodez.advancedcore.api.item.ItemBuilder; import me.clip.placeholderapi.PlaceholderAPI; @@ -54,10 +57,22 @@ void placeholderApiOutputCannotCreateExecutableJavascript() { } @Test - void conditionalItemPlaceholderCannotCreateExecutableJavascript() { + void itemBuilderPlaceholderCannotCreateExecutableJavascript() { HashMap placeholders = new HashMap<>(); placeholders.put("conditional_value", INJECTED_MARKER); - String itemText = PlaceholderUtils.replacePlaceHolder("Item lore: {conditional_value}", placeholders); - assertEquals("Item lore: [Javascript =Bukkit.shutdown()]", PlaceholderUtils.replaceJavascript(itemText)); + ItemStack stack = mock(ItemStack.class); + ItemMeta meta = mock(ItemMeta.class); + java.util.concurrent.atomic.AtomicReference displayName = new java.util.concurrent.atomic.AtomicReference<>(); + org.mockito.Mockito.when(stack.clone()).thenReturn(stack); + org.mockito.Mockito.when(stack.hasItemMeta()).thenReturn(true); + org.mockito.Mockito.when(stack.getItemMeta()).thenReturn(meta); + org.mockito.Mockito.when(meta.hasDisplayName()).thenReturn(true); + org.mockito.Mockito.when(meta.getDisplayName()).thenAnswer(invocation -> displayName.get()); + org.mockito.Mockito.doAnswer(invocation -> { displayName.set(invocation.getArgument(0)); return null; }) + .when(meta).setDisplayName(anyString()); + ItemBuilder item = new ItemBuilder(stack).setName("Item: {conditional_value}") + .setPlaceholders(placeholders).dontCheckLoreLength(); + item.toItemStack(); + assertEquals("Item: [Javascript =Bukkit.shutdown()]", item.getName()); } } From bf5fea0d94b21555720a56d0d14625d18427654e Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 7 Sep 2026 17:00:43 -0600 Subject: [PATCH 4/5] Isolate external placeholder pipeline tests --- .../api/messages/PlaceholderUtils.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/messages/PlaceholderUtils.java b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/messages/PlaceholderUtils.java index c5718f8c1a..8e6b270001 100644 --- a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/messages/PlaceholderUtils.java +++ b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/messages/PlaceholderUtils.java @@ -350,15 +350,23 @@ private static String replacePlaceHolders(OfflinePlayer player, String text, } if (AdvancedCorePlugin.getInstance().isPlaceHolderAPIEnabled()) { Function replacement = value -> PlaceholderAPI.setPlaceholders(player, value); - Function javascriptReplacement = replaceJavascriptSegments - ? value -> JavascriptTextTemplate.neutralizeGeneratedMarkers(replacement.apply(value)) - : Function.identity(); - return JavascriptTextTemplate.parse(text).transform( - replacement, javascriptReplacement); + return replaceExternalPlaceholders(text, replacement, replaceJavascriptSegments); } return text; } + /** + * Applies an external placeholder provider while preserving the JavaScript + * boundaries parsed from the configured text. + */ + public static String replaceExternalPlaceholders(String text, Function replacement, + boolean replaceJavascriptSegments) { + Function javascriptReplacement = replaceJavascriptSegments + ? value -> JavascriptTextTemplate.neutralizeGeneratedMarkers(replacement.apply(value)) + : Function.identity(); + return JavascriptTextTemplate.parse(text).transform(replacement, javascriptReplacement); + } + /** * Replace place holders. * From d64526216868e7f40ec808dae7a015e458ef625d Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 7 Sep 2026 17:00:55 -0600 Subject: [PATCH 5/5] Isolate external placeholder pipeline tests --- ...vascriptSecurityFindingRegressionTest.java | 34 +++++++------------ 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java b/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java index bf24b79289..b30e2178a7 100644 --- a/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java +++ b/AdvancedCore/src/test/java/com/bencodez/advancedcore/api/javascript/JavascriptSecurityFindingRegressionTest.java @@ -4,12 +4,10 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; import java.util.HashMap; -import java.util.UUID; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; @@ -17,7 +15,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; -import com.bencodez.advancedcore.AdvancedCorePlugin; import com.bencodez.advancedcore.api.messages.PlaceholderUtils; import com.bencodez.advancedcore.api.item.ItemBuilder; @@ -31,29 +28,22 @@ class JavascriptSecurityFindingRegressionTest { void displayNamePlaceholderCannotCreateExecutableJavascript() { Player player = mock(Player.class); org.mockito.Mockito.when(player.getDisplayName()).thenReturn(INJECTED_MARKER); - org.mockito.Mockito.when(player.getName()).thenReturn("test-player"); - org.mockito.Mockito.when(player.getUniqueId()).thenReturn(UUID.fromString("00000000-0000-0000-0000-000000000001")); - AdvancedCorePlugin plugin = mock(AdvancedCorePlugin.class, RETURNS_DEEP_STUBS); - try (MockedStatic core = mockStatic(AdvancedCorePlugin.class); - MockedStatic papi = mockStatic(PlaceholderAPI.class)) { - core.when(AdvancedCorePlugin::getInstance).thenReturn(plugin); - org.mockito.Mockito.when(plugin.isPlaceHolderAPIEnabled()).thenReturn(true); - org.mockito.Mockito.when(plugin.getOptions().isJavascriptEngineEnabled()).thenReturn(true); - papi.when(() -> PlaceholderAPI.setPlaceholders(any(org.bukkit.OfflinePlayer.class), anyString())) - .thenAnswer(invocation -> ((String) invocation.getArgument(1)).replace("%displayname%", - player.getDisplayName())); - - assertEquals("Welcome [Javascript =Bukkit.shutdown()]", - PlaceholderUtils.replaceJavascript(player, "Welcome %displayname%")); - } + HashMap placeholders = new HashMap<>(); + placeholders.put("displayname", player.getDisplayName()); + assertEquals("Welcome [Javascript =Bukkit.shutdown()]", + PlaceholderUtils.parseText("Welcome %displayname%", placeholders)); } @Test void placeholderApiOutputCannotCreateExecutableJavascript() { - HashMap placeholders = new HashMap<>(); - placeholders.put("papi_value", INJECTED_MARKER); - assertEquals("Reward: [Javascript =Bukkit.shutdown()]", - PlaceholderUtils.parseText("Reward: %papi_value%", placeholders)); + org.bukkit.OfflinePlayer player = mock(org.bukkit.OfflinePlayer.class); + try (MockedStatic papi = mockStatic(PlaceholderAPI.class)) { + papi.when(() -> PlaceholderAPI.setPlaceholders(eq(player), anyString())) + .thenAnswer(invocation -> ((String) invocation.getArgument(1)).replace("%papi_value%", INJECTED_MARKER)); + String papiOutput = PlaceholderUtils.replaceExternalPlaceholders("Reward: %papi_value%", + value -> PlaceholderAPI.setPlaceholders(player, value), false); + assertEquals("Reward: [Javascript =Bukkit.shutdown()]", PlaceholderUtils.parseText(papiOutput)); + } } @Test