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

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 142042f25 fix(acl): validate plain permission entries (#2563)
142042f25 is described below

commit 142042f25bf1a1df4851cf99d98df9eb9a7f5d3e
Author: btlqql <[email protected]>
AuthorDate: Tue Aug 25 17:37:25 2026 +0800

    fix(acl): validate plain permission entries (#2563)
---
 .../studio/instance/acl/MybatisPlusAclRepository.java   | 15 +++++++++++++++
 .../instance/acl/MybatisPlusAclRepositoryTest.java      | 17 +++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/instance/acl/MybatisPlusAclRepository.java
 
b/server/src/main/java/org/apache/rocketmq/studio/instance/acl/MybatisPlusAclRepository.java
index 4ab94bd05..76d7520f0 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/instance/acl/MybatisPlusAclRepository.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/instance/acl/MybatisPlusAclRepository.java
@@ -177,6 +177,8 @@ public class MybatisPlusAclRepository implements 
AclRepository {
     @Override
     @Transactional
     public PlainAccessConfigVO 
createAndUpdatePlainAccessConfig(PlainAccessConfigVO config) {
+        validatePermissionEntries(config.getTopicPerms(), "topicPerms");
+        validatePermissionEntries(config.getGroupPerms(), "groupPerms");
         List<RmqAclUser> existingAccounts = userMapper.selectList(
                 new QueryWrapper<RmqAclUser>().eq("access_key", 
config.getAccessKey()));
         if (existingAccounts.size() > 1) {
@@ -356,6 +358,19 @@ public class MybatisPlusAclRepository implements 
AclRepository {
         return new String[]{entry.substring(0, idx).trim(), 
entry.substring(idx + 1).trim()};
     }
 
+    private static void validatePermissionEntries(List<String> entries, String 
field) {
+        if (entries == null) {
+            return;
+        }
+        for (int index = 0; index < entries.size(); index++) {
+            String[] parts = splitPerm(entries.get(index));
+            if (parts == null || parts[0].isBlank() || parts[1].isBlank()) {
+                throw new BusinessException(400,
+                        field + "[" + index + "] must use non-blank 
resource=permission format");
+            }
+        }
+    }
+
     // ── Mapping ────────────────────────────────────────────────────
 
     private static AclRuleVO toRuleVO(RmqAclRule entity) {
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/instance/acl/MybatisPlusAclRepositoryTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/instance/acl/MybatisPlusAclRepositoryTest.java
index a7a5fc195..21626d723 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/instance/acl/MybatisPlusAclRepositoryTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/instance/acl/MybatisPlusAclRepositoryTest.java
@@ -48,6 +48,7 @@ import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
 import static org.mockito.Mockito.when;
 
 @ExtendWith(MockitoExtension.class)
@@ -62,6 +63,22 @@ class MybatisPlusAclRepositoryTest {
     @InjectMocks
     private MybatisPlusAclRepository repository;
 
+    @Test
+    void upsertShouldRejectMalformedPermissionEntriesBeforeMutatingAccount() {
+        PlainAccessConfigVO config = PlainAccessConfigVO.builder()
+                .accessKey("svc-x")
+                .secretKey("secret-x")
+                .topicPerms(List.of("orders=PUB", "missing-permission"))
+                .build();
+
+        assertThatThrownBy(() -> 
repository.createAndUpdatePlainAccessConfig(config))
+                .isInstanceOf(BusinessException.class)
+                .hasMessage("topicPerms[1] must use non-blank 
resource=permission format")
+                .satisfies(error -> assertThat(((BusinessException) 
error).getCode()).isEqualTo(400));
+
+        verifyNoInteractions(userMapper, ruleMapper);
+    }
+
     @Test
     void findRulePageShouldApplyFiltersAndPreserveFilteredTotal() {
         RmqAclRule entity = new RmqAclRule();

Reply via email to