This is an automated email from the ASF dual-hosted git repository.

PragmaTwice pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git


The following commit(s) were added to refs/heads/unstable by this push:
     new 47e08935c fix(replication): require admin for transfer commands (#3484)
47e08935c is described below

commit 47e08935c6fb4ec604d4d650860abca546b83c51
Author: hulk <[email protected]>
AuthorDate: Mon May 11 12:22:55 2026 +0800

    fix(replication): require admin for transfer commands (#3484)
    
    Mark PSYNC, _FETCH_META, and _FETCH_FILE as admin-only commands so
    namespace users cannot invoke replication transfer internals.
    
    Move the regression coverage into the integration replication suite,
    where the command behavior is exercised against a running server.
    
    Assisted-by: Codex/GPT 5.5 xhigh
---
 src/commands/cmd_replication.cc                    |  6 ++---
 .../integration/replication/replication_test.go    | 30 ++++++++++++++++++++++
 2 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/src/commands/cmd_replication.cc b/src/commands/cmd_replication.cc
index 73fbca830..9f15ed1e4 100644
--- a/src/commands/cmd_replication.cc
+++ b/src/commands/cmd_replication.cc
@@ -483,9 +483,9 @@ class CommandWait : public Commander,
 };
 
 REDIS_REGISTER_COMMANDS(Replication, MakeCmdAttr<CommandReplConf>("replconf", 
-3, "read-only no-script", NO_KEY),
-                        MakeCmdAttr<CommandPSync>("psync", -2, "read-only 
no-multi no-script", NO_KEY),
-                        MakeCmdAttr<CommandFetchMeta>("_fetch_meta", 1, 
"read-only no-multi no-script", NO_KEY),
-                        MakeCmdAttr<CommandFetchFile>("_fetch_file", 2, 
"read-only no-multi no-script", NO_KEY),
+                        MakeCmdAttr<CommandPSync>("psync", -2, "read-only 
no-multi no-script admin", NO_KEY),
+                        MakeCmdAttr<CommandFetchMeta>("_fetch_meta", 1, 
"read-only no-multi no-script admin", NO_KEY),
+                        MakeCmdAttr<CommandFetchFile>("_fetch_file", 2, 
"read-only no-multi no-script admin", NO_KEY),
                         MakeCmdAttr<CommandDBName>("_db_name", 1, "read-only 
no-multi", NO_KEY),
                         MakeCmdAttr<CommandWait>("wait", 3, "read-only 
no-multi no-script blocking", NO_KEY), )
 
diff --git a/tests/gocase/integration/replication/replication_test.go 
b/tests/gocase/integration/replication/replication_test.go
index 6e291ecc5..23ccabd10 100644
--- a/tests/gocase/integration/replication/replication_test.go
+++ b/tests/gocase/integration/replication/replication_test.go
@@ -117,6 +117,36 @@ func TestReplicationWithHostname(t *testing.T) {
        })
 }
 
+func TestReplicationTransferCommandsRequireAdminPermission(t *testing.T) {
+       srv := util.StartServer(t, map[string]string{
+               "requirepass": "admin",
+       })
+       defer srv.Close()
+
+       ctx := context.Background()
+       adminClient := srv.NewClientWithOption(&redis.Options{Password: 
"admin"})
+       defer func() { require.NoError(t, adminClient.Close()) }()
+
+       require.NoError(t, adminClient.Do(ctx, "NAMESPACE", "ADD", "test_ns", 
"test_token").Err())
+
+       userClient := srv.NewClientWithOption(&redis.Options{Password: 
"test_token"})
+       defer func() { require.NoError(t, userClient.Close()) }()
+
+       for _, cmd := range []struct {
+               name string
+               args []interface{}
+       }{
+               {name: "PSYNC", args: []interface{}{"1"}},
+               {name: "_FETCH_META"},
+               {name: "_FETCH_FILE", args: []interface{}{"MANIFEST-000001"}},
+       } {
+               t.Run(cmd.name, func(t *testing.T) {
+                       args := append([]interface{}{cmd.name}, cmd.args...)
+                       require.ErrorContains(t, userClient.Do(ctx, 
args...).Err(), "admin permission required to perform the command")
+               })
+       }
+}
+
 func TestReplicationLoading(t *testing.T) {
        t.Parallel()
        srvA := util.StartServer(t, map[string]string{})

Reply via email to