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

CalvinKirs pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 342fd131046 [Fix](auth) Restrict processlist visibility by user 
identity (#66746)
342fd131046 is described below

commit 342fd131046b2a74a79dab22e7043e4c8ef73669
Author: linrrarity <[email protected]>
AuthorDate: Mon Aug 24 09:49:59 2026 +0800

    [Fix](auth) Restrict processlist visibility by user identity (#66746)
    
    Problem Summary:
    
    Authenticated non-admin users could inspect sessions and active SQL
    statements belonging to other users through
    `information_schema.processlist`, `SHOW PROCESSLIST`
    
    ```sql
    CREATE USER 'pl_victim' IDENTIFIED BY 'C123_567p';
    CREATE USER 'pl_attacker' IDENTIFIED BY 'C123_567p';
    
    GRANT SELECT_PRIV ON processlist_demo.* TO 'pl_victim';
    GRANT SELECT_PRIV ON processlist_demo.* TO 'pl_attacker';
    
    -- victim
    SELECT SLEEP(120), 'victim_secret_token=demo-only-123';
    
    -- attacker
    SELECT User, Command, Info
    FROM information_schema.processlist
    WHERE User = 'pl_victim';
    
+-------------+---------+-------------------------------------------------------------------------------------------------------------------------+
    | User        | Command | Info                                              
                                                                      |
    
+-------------+---------+-------------------------------------------------------------------------------------------------------------------------+
    | pl_attacker | Query   | SELECT User, Command, Info
    FROM information_schema.processlist
    WHERE User IN ('pl_victim', 'pl_attacker')
    ORDER BY User |
    | pl_victim   | Query   | SELECT SLEEP(120), 
'victim_secret_token=demo-only-123'                                             
                     |
    
+-------------+---------+-------------------------------------------------------------------------------------------------------------------------+
    
    ```
    The schema scanners did not consistently propagate the caller's user
    identity to FE, and the FE metadata handlers did not always enforce
    per-user visibility.
    
    
    ### Release note
    
    Non-admin users can now see only their own sessions and active queries
    through processlist and information_schema.active_queries. ADMIN users
    retain cluster-wide visibility.
---
 .../schema_processlist_scanner.cpp                 |  1 +
 .../apache/doris/service/FrontendServiceImpl.java  | 10 ++---
 .../doris/service/FrontendServiceImplTest.java     | 10 +++++
 .../suites/show_p0/test_show_processlist.groovy    | 48 +++++++++++++++++++++-
 4 files changed, 63 insertions(+), 6 deletions(-)

diff --git a/be/src/information_schema/schema_processlist_scanner.cpp 
b/be/src/information_schema/schema_processlist_scanner.cpp
index 9fb80e9a651..ace3081238b 100644
--- a/be/src/information_schema/schema_processlist_scanner.cpp
+++ b/be/src/information_schema/schema_processlist_scanner.cpp
@@ -58,6 +58,7 @@ Status SchemaProcessListScanner::start(RuntimeState* state) {
     TShowProcessListRequest request;
     request.__set_show_full_sql(true);
     request.__set_time_zone(state->timezone());
+    
request.__set_current_user_ident(*_param->common_param->current_user_ident);
 
     for (const auto& fe_addr : _param->common_param->fe_addr_list) {
         TShowProcessListResult tmp_ret;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java 
b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
index 486b27b6a43..ea4c8c18a06 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
@@ -5626,15 +5626,15 @@ public class FrontendServiceImpl implements 
FrontendService.Iface {
     }
 
     @Override
-    public TShowProcessListResult showProcessList(TShowProcessListRequest 
request) {
+    public TShowProcessListResult showProcessList(TShowProcessListRequest 
request) throws TException {
+        if (!request.isSetCurrentUserIdent()) {
+            throw new TException("Current user identity is not set");
+        }
         boolean isShowFullSql = false;
         if (request.isSetShowFullSql()) {
             isShowFullSql = request.isShowFullSql();
         }
-        UserIdentity userIdentity = UserIdentity.ROOT;
-        if (request.isSetCurrentUserIdent()) {
-            userIdentity = 
UserIdentity.fromThrift(request.getCurrentUserIdent());
-        }
+        UserIdentity userIdentity = 
UserIdentity.fromThrift(request.getCurrentUserIdent());
         String timeZone = 
VariableMgr.getDefaultSessionVariable().getTimeZone();
         if (request.isSetTimeZone()) {
             timeZone = request.getTimeZone();
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
index 03fde60682b..bc5bb4d8aab 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
@@ -64,6 +64,7 @@ import org.apache.doris.thrift.TPrivilegeType;
 import org.apache.doris.thrift.TRollbackTxnRequest;
 import org.apache.doris.thrift.TSchemaTableName;
 import org.apache.doris.thrift.TSchemaTableRequestParams;
+import org.apache.doris.thrift.TShowProcessListRequest;
 import org.apache.doris.thrift.TShowUserRequest;
 import org.apache.doris.thrift.TShowUserResult;
 import org.apache.doris.thrift.TStatusCode;
@@ -76,6 +77,7 @@ import org.apache.doris.utframe.TestWithFeService;
 
 import com.google.common.collect.Sets;
 import org.apache.logging.log4j.Level;
+import org.apache.thrift.TException;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.MockedStatic;
@@ -153,6 +155,14 @@ public class FrontendServiceImplTest extends 
TestWithFeService {
         }
     }
 
+    public void testShowProcessListRejectsMissingUserIdentity() {
+        FrontendServiceImpl impl = new FrontendServiceImpl(exeEnv);
+        TShowProcessListRequest request = new TShowProcessListRequest();
+
+        TException exception = Assertions.assertThrows(TException.class, () -> 
impl.showProcessList(request));
+        Assertions.assertEquals("Current user identity is not set", 
exception.getMessage());
+    }
+
     @Test
     public void testGetTableNamesWithSysTablePattern() throws Exception {
         FrontendServiceImpl impl = new FrontendServiceImpl(exeEnv);
diff --git a/regression-test/suites/show_p0/test_show_processlist.groovy 
b/regression-test/suites/show_p0/test_show_processlist.groovy
index 8c27e2f02a2..237aed9c2a5 100644
--- a/regression-test/suites/show_p0/test_show_processlist.groovy
+++ b/regression-test/suites/show_p0/test_show_processlist.groovy
@@ -18,6 +18,20 @@
 import org.apache.doris.regression.util.Http
 
 suite("test_show_processlist") {
+    def victimUser = "test_processlist_victim"
+    def attackerUser = "test_processlist_attacker"
+    def userPassword = "C123_567p"
+    try_sql "DROP USER '${victimUser}'"
+    try_sql "DROP USER '${attackerUser}'"
+    sql "CREATE USER '${victimUser}' IDENTIFIED BY '${userPassword}'"
+    sql "CREATE USER '${attackerUser}' IDENTIFIED BY '${userPassword}'"
+    sql "GRANT SELECT_PRIV ON regression_test.* TO '${victimUser}'"
+    sql "GRANT SELECT_PRIV ON regression_test.* TO '${attackerUser}'"
+    if (isCloudMode()) {
+        sql "GRANT USAGE_PRIV ON COMPUTE GROUP '%' TO '${victimUser}'"
+        sql "GRANT USAGE_PRIV ON COMPUTE GROUP '%' TO '${attackerUser}'"
+    }
+
     sql """set fetch_all_fe_for_system_table = false;"""
     def result = sql """show processlist;"""
     logger.info("result:${result}")
@@ -42,7 +56,39 @@ suite("test_show_processlist") {
     logger.info("result:${result}")
     assertTrue(result[0].size() == 15)
 
-    
+    connect(victimUser, userPassword, context.config.jdbcUrl) {
+        sql "select 1"
+        connect(attackerUser, userPassword, context.config.jdbcUrl) {
+            def attackerRows = sql """
+                SELECT User, Info
+                FROM information_schema.processlist
+                WHERE User IN ('${victimUser}', '${attackerUser}')
+                ORDER BY User
+            """
+            assertFalse(attackerRows.isEmpty())
+            assertTrue(attackerRows.every { row -> row[0] == attackerUser })
+            assertFalse(attackerRows.any { row -> row[0] == victimUser })
+            assertTrue(attackerRows.any { row ->
+                row[1] != null && 
row[1].toString().contains("information_schema.processlist")
+            })
+
+            def showRows = sql "SHOW FULL PROCESSLIST"
+            assertFalse(showRows.isEmpty())
+            assertTrue(showRows.every { row -> row[2] == attackerUser })
+
+            connect('root', context.config.jdbcPassword, 
context.config.jdbcUrl) {
+                def adminRows = sql """
+                    SELECT User
+                    FROM information_schema.processlist
+                    WHERE User IN ('${victimUser}', '${attackerUser}')
+                    ORDER BY User
+                """
+                assertTrue(adminRows.any { row -> row[0] == victimUser })
+                assertTrue(adminRows.any { row -> row[0] == attackerUser })
+            }
+        }
+    }
+
     def result1 = connect('root', context.config.jdbcPassword, 
context.config.jdbcUrl) {
         // execute sql with admin user
         sql 'select 99 + 1'


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to