diff --git a/includes/functions.php b/includes/functions.php
index 6ae758fff4ee3e1a6fde53f936366b29392fcef0..9138fbc1fbf9d31cb59bacfbaf70997399b51758 100644
--- a/includes/functions.php
+++ b/includes/functions.php
@@ -75,6 +75,11 @@ function validate_command( $command ) {
  * @return bool
  */
 function is_command_allowed( $command ) {
+	// No recursion allowed.
+	if ( CLI_NAMESPACE === $command ) {
+		return false;
+	}
+
 	// Command explicitly disallowed.
 	if ( in_array( $command, get_command_blacklist(), true ) ) {
 		return false;
diff --git a/tests/tests/class-plugin-functions.php b/tests/tests/class-plugin-functions.php
index 2845bbc65a602f1fd8b7e514e06ae062a7eb296a..fe035e061b4012ff4cef733ca9228b367aeafe88 100644
--- a/tests/tests/class-plugin-functions.php
+++ b/tests/tests/class-plugin-functions.php
@@ -128,6 +128,7 @@ class Plugin_Functions extends WP_UnitTestCase {
 			array( 'wp cli info' ), // Should fail, is a blocked event.
 			array( 'wp cli info' ), // Should fail as a blocked event, would otherwise fail as a duplicate.
 			array( 'cli info' ), // Should also fail as a blocked event, though normalization would also block it as a duplicate.
+			array( sprintf( '%s create', WP_CLI_Cron_Control_Offload\CLI_NAMESPACE ) ), // Don't permit recursive scheduling.
 		);
 	}