diff --git a/patches/server/Added-missing-default-perms-for-commands.patch b/patches/server/Added-missing-default-perms-for-commands.patch
index aa1f7c7189..64468fc04c 100644
--- a/patches/server/Added-missing-default-perms-for-commands.patch
+++ b/patches/server/Added-missing-default-perms-for-commands.patch
@@ -9,15 +9,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 --- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
 +++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java
 @@ -0,0 +0,0 @@ public final class CommandPermissions {
+         DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "list", "Allows the user to list all online players", PermissionDefault.OP, commands);
+         DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "gamemode", "Allows the user to change the gamemode of another player", PermissionDefault.OP, commands);
+         DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "xp", "Allows the user to give themselves or others arbitrary values of experience", PermissionDefault.OP, commands);
+-        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "toggledownfall", "Allows the user to toggle rain on/off for a given world", PermissionDefault.OP, commands);
+         DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "defaultgamemode", "Allows the user to change the default gamemode of the server", PermissionDefault.OP, commands);
+         DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "seed", "Allows the user to view the seed of the world", PermissionDefault.OP, commands);
          DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands);
          DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands);
          DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands);
 +        // Paper start
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands);
-+        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban", "Allows the user to add players to banlist", PermissionDefault.OP, commands);
-+        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban-ip", "Allows the user to add ip address to banlist", PermissionDefault.OP, commands);
-+        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "banlist", "Allows the user to display banlist", PermissionDefault.OP, commands);
++        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban", "Allows the user to add players to the ban list", PermissionDefault.OP, commands);
++        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban-ip", "Allows the user to add ip address to the ban list", PermissionDefault.OP, commands);
++        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "banlist", "Allows the user to display the ban list", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands);
@@ -32,12 +38,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands);
++        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "jfr", "Allows a user to use the vanilla Java FlightRecorder profiling system", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "locatebiome", "Allows the user to locate the closest biome", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands);
-+        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "pardon", "Allows the user to remove entries from the banlist", PermissionDefault.OP, commands);
++        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "pardon", "Allows the user to remove entries from the player ban list", PermissionDefault.OP, commands);
++        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "pardon-ip", "Allows the user to remove entries from the ip address ban list", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands);
++        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "perf", "Allows the user to start/stop the vanilla performance metrics capture", PermissionDefault.OP, commands);
++        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "placefeature", "Allows the user to place features with the command", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands);
 +        DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands);
@@ -68,3 +78,128 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
          DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands);
  
+diff --git a/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
+--- /dev/null
++++ b/src/test/java/io/papermc/paper/permissions/MinecraftCommandPermissionsTest.java
+@@ -0,0 +0,0 @@
++package io.papermc.paper.permissions;
++
++import com.mojang.brigadier.tree.CommandNode;
++import com.mojang.brigadier.tree.RootCommandNode;
++import net.minecraft.commands.CommandSourceStack;
++import net.minecraft.commands.Commands;
++import net.minecraft.server.Bootstrap;
++import org.bukkit.Bukkit;
++import org.bukkit.craftbukkit.command.VanillaCommandWrapper;
++import org.bukkit.craftbukkit.util.permissions.CraftDefaultPermissions;
++import org.bukkit.permissions.Permission;
++import org.bukkit.support.AbstractTestingBase;
++import org.junit.AfterClass;
++import org.junit.BeforeClass;
++import org.junit.Test;
++
++import java.io.PrintStream;
++import java.util.HashSet;
++import java.util.LinkedHashSet;
++import java.util.List;
++import java.util.Set;
++import java.util.TreeSet;
++
++import static org.junit.Assert.assertTrue;
++
++public class MinecraftCommandPermissionsTest extends AbstractTestingBase {
++
++    private static PrintStream old;
++    @BeforeClass
++    public static void before() {
++        old = System.out;
++        System.setOut(Bootstrap.STDOUT);
++    }
++
++    @Test
++    public void test() {
++        CraftDefaultPermissions.registerCorePermissions();
++        Set<String> perms = collectMinecraftCommandPerms();
++
++        Commands commands = new Commands(Commands.CommandSelection.DEDICATED);
++        RootCommandNode<CommandSourceStack> root = commands.getDispatcher().getRoot();
++        Set<String> missing = new LinkedHashSet<>();
++        Set<String> foundPerms = new HashSet<>();
++        for (CommandNode<CommandSourceStack> child : root.getChildren()) {
++            final String vanillaPerm = VanillaCommandWrapper.getPermission(child);
++            if (!perms.contains(vanillaPerm)) {
++                missing.add("Missing permission for " + child.getName() + " (" + vanillaPerm + ") command");
++            } else {
++                foundPerms.add(vanillaPerm);
++            }
++        }
++        assertTrue("Commands missing permissions: \n" + String.join("\n", missing), missing.isEmpty());
++        perms.removeAll(foundPerms);
++        assertTrue("Extra permissions not associated with a command: \n" + String.join("\n", perms), perms.isEmpty());
++    }
++
++    private static final List<String> TO_SKIP = List.of(
++        "minecraft.command.selector"
++    );
++
++    private static Set<String> collectMinecraftCommandPerms() {
++        Set<String> perms = new TreeSet<>();
++        for (Permission perm : Bukkit.getPluginManager().getPermissions()) {
++            if (perm.getName().startsWith("minecraft.command.")) {
++                if (TO_SKIP.contains(perm.getName())) {
++                    continue;
++                }
++                if (perm.getName().endsWith(".xp")) {
++                    perms.add("minecraft.command.experience"); // for the "experience" command, craftbukkit perm is "minecraft.command.xp"
++                    continue;
++                }
++                perms.add(perm.getName());
++            }
++        }
++        return perms;
++    }
++
++    @AfterClass
++    public static void after() {
++        if (old != null) {
++            System.setOut(old);
++        }
++    }
++}
+diff --git a/src/test/java/org/bukkit/support/DummyServer.java b/src/test/java/org/bukkit/support/DummyServer.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/test/java/org/bukkit/support/DummyServer.java
++++ b/src/test/java/org/bukkit/support/DummyServer.java
+@@ -0,0 +0,0 @@ public final class DummyServer implements InvocationHandler {
+                         }
+                     }
+                 );
+-            Bukkit.setServer(Proxy.getProxyClass(Server.class.getClassLoader(), Server.class).asSubclass(Server.class).getConstructor(InvocationHandler.class).newInstance(new DummyServer()));
++            // Paper start - modeled off of TestServer in the API tests module
++            methods.put(
++                Server.class.getMethod("getPluginManager"),
++                new MethodHandler() {
++                    @Override
++                    public Object handle(DummyServer server, Object[] args) {
++                        return server.pluginManager;
++                    }
++                }
++            );
++            DummyServer server = new DummyServer();
++            Server instance = Proxy.getProxyClass(Server.class.getClassLoader(), Server.class).asSubclass(Server.class).getConstructor(InvocationHandler.class).newInstance(server);
++            Bukkit.setServer(instance);
++            server.pluginManager = new org.bukkit.plugin.SimplePluginManager(instance, new org.bukkit.command.SimpleCommandMap(instance));
++            // Paper end
+         } catch (Throwable t) {
+             throw new Error(t);
+         }
+@@ -0,0 +0,0 @@ public final class DummyServer implements InvocationHandler {
+ 
+     private DummyServer() {};
+ 
++    private org.bukkit.plugin.PluginManager pluginManager; // Paper
+     @Override
+     public Object invoke(Object proxy, Method method, Object[] args) {
+         MethodHandler handler = DummyServer.methods.get(method);