From 11d9c703c01eec9d5135a8edadc1c9025603c487 Mon Sep 17 00:00:00 2001 From: Ben Date: Sat, 8 Aug 2026 16:05:14 -0600 Subject: [PATCH] Prevent placeholder output from executing JavaScript --- .../api/messages/PlaceholderUtils.java | 35 +++++++++++++++++ .../advancedcore/api/misc/MiscUtils.java | 22 +++++++---- .../tests/messages/PlaceholderUtilsTest.java | 38 +++++++++++++++++++ 3 files changed, 87 insertions(+), 8 deletions(-) create mode 100644 AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/messages/PlaceholderUtilsTest.java 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 42ea26693..8e74bb82d 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 @@ -181,6 +181,25 @@ public static String replaceJavascript(OfflinePlayer player, String text) { return text; } + public static ArrayList replaceJavascriptOnly(OfflinePlayer player, ArrayList list) { + ArrayList msg = new ArrayList<>(); + for (String str : list) { + msg.add(replaceJavascriptOnly(player, str)); + } + return msg; + } + + public static String replaceJavascriptOnly(OfflinePlayer player, String text) { + if (AdvancedCorePlugin.getInstance().getOptions().isJavascriptEngineEnabled()) { + if (player.isOnline()) { + return replaceJavascriptOnly(player.getPlayer(), text); + } + JavascriptEngine engine = new JavascriptEngine().addPlayer(player); + return replaceJavascript(text, engine); + } + return text; + } + public static ArrayList replaceJavascript(Player player, ArrayList list) { ArrayList msg = new ArrayList<>(); for (String str : list) { @@ -198,6 +217,22 @@ public static String replaceJavascript(Player player, String text) { return msg; } + public static ArrayList replaceJavascriptOnly(Player player, ArrayList list) { + ArrayList msg = new ArrayList<>(); + for (String str : list) { + msg.add(replaceJavascriptOnly(player, str)); + } + return msg; + } + + public static String replaceJavascriptOnly(Player player, String text) { + if (AdvancedCorePlugin.getInstance().getOptions().isJavascriptEngineEnabled()) { + JavascriptEngine engine = new JavascriptEngine().addPlayer(player); + return replaceJavascript(text, engine); + } + return text; + } + public static String replaceJavascript(String text) { return replaceJavascript(text, null); } diff --git a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/misc/MiscUtils.java b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/misc/MiscUtils.java index cacd5b93e..c5cc38636 100644 --- a/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/misc/MiscUtils.java +++ b/AdvancedCore/src/main/java/com/bencodez/advancedcore/api/misc/MiscUtils.java @@ -174,11 +174,11 @@ public void executeConsoleCommands(final Player player, final ArrayList final HashMap placeholders, boolean stagger) { if (cmds != null && !cmds.isEmpty()) { placeholders.put("player", player.getName()); - ArrayList commands = PlaceholderUtils.replacePlaceHolder(cmds, placeholders); + ArrayList commands = PlaceholderUtils.replaceJavascriptOnly(player, cmds); + commands = PlaceholderUtils.replacePlaceHolder(commands, placeholders); commands = PlaceholderUtils.replacePlaceHolders(commands, player); - final ArrayList finalCommands = PlaceholderUtils.replaceJavascript(player, commands); int tick = 0; - for (final String cmd : finalCommands) { + for (final String cmd : commands) { plugin.debug("Executing console command: " + cmd); runConsoleCommand(cmd, tick, stagger); } @@ -188,9 +188,10 @@ public void executeConsoleCommands(final Player player, final ArrayList public void executeConsoleCommands(Player player, String command, HashMap placeholders) { if (command != null && !command.isEmpty()) { - String cmd = PlaceholderUtils.replacePlaceHolder(command, placeholders); + String cmd = PlaceholderUtils.replaceJavascriptOnly(player, command); + cmd = PlaceholderUtils.replacePlaceHolder(cmd, placeholders); cmd = PlaceholderUtils.replacePlaceHolders(player, cmd); - final String finalCommand = PlaceholderUtils.replaceJavascript(player, cmd); + final String finalCommand = cmd; plugin.debug("Executing console command: " + command); plugin.getBukkitScheduler().executeOrScheduleSync(plugin, new Runnable() { @@ -211,10 +212,13 @@ public void executeConsoleCommands(final String playerName, final ArrayList commands = PlaceholderUtils.replacePlaceHolder(cmds, placeholders); + ArrayList commands = cmds; + if (p != null) { + commands = PlaceholderUtils.replaceJavascriptOnly(p, commands); + } + commands = PlaceholderUtils.replacePlaceHolder(commands, placeholders); if (p != null) { commands = PlaceholderUtils.replacePlaceHolders(p, commands); - commands = PlaceholderUtils.replaceJavascript(p, commands); } int tick = 0; for (final String cmd : commands) { @@ -227,10 +231,12 @@ public void executeConsoleCommands(final String playerName, final ArrayList placeholders) { if (command != null && !command.isEmpty()) { OfflinePlayer p = Bukkit.getOfflinePlayer(playerName); + if (p != null) { + command = PlaceholderUtils.replaceJavascriptOnly(p, command); + } command = PlaceholderUtils.replacePlaceHolder(command, placeholders); if (p != null) { command = PlaceholderUtils.replacePlaceHolders(p, command); - command = PlaceholderUtils.replaceJavascript(p, command); } if (command.startsWith("/")) { command.replaceFirst("/", ""); diff --git a/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/messages/PlaceholderUtilsTest.java b/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/messages/PlaceholderUtilsTest.java new file mode 100644 index 000000000..a2f5b0ee8 --- /dev/null +++ b/AdvancedCore/src/test/java/com/bencodez/advancedcore/tests/messages/PlaceholderUtilsTest.java @@ -0,0 +1,38 @@ +package com.bencodez.advancedcore.tests.messages; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +import org.bukkit.entity.Player; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; + +import com.bencodez.advancedcore.AdvancedCoreConfigOptions; +import com.bencodez.advancedcore.AdvancedCorePlugin; +import com.bencodez.advancedcore.api.messages.PlaceholderUtils; + +import me.clip.placeholderapi.PlaceholderAPI; + +public class PlaceholderUtilsTest { + + @Test + public void replaceJavascriptOnlyDoesNotExpandPlaceholderApiOutput() { + AdvancedCorePlugin plugin = mock(AdvancedCorePlugin.class); + AdvancedCoreConfigOptions options = mock(AdvancedCoreConfigOptions.class); + Player player = mock(Player.class); + String command = "say %untrusted%"; + + when(plugin.getOptions()).thenReturn(options); + when(options.isJavascriptEngineEnabled()).thenReturn(false); + + try (MockedStatic pluginStatic = mockStatic(AdvancedCorePlugin.class); + MockedStatic placeholderApiStatic = mockStatic(PlaceholderAPI.class)) { + pluginStatic.when(AdvancedCorePlugin::getInstance).thenReturn(plugin); + + assertEquals(command, PlaceholderUtils.replaceJavascriptOnly(player, command)); + placeholderApiStatic.verifyNoInteractions(); + } + } +}