Copilot commented on code in PR #2945:
URL: 
https://github.com/apache/incubator-hugegraph/pull/2945#discussion_r2740417738


##########
hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/controller/PartitionAPI.java:
##########
@@ -225,6 +247,34 @@ public Map<String, Object> okMap(String k, Object v) {
         return map;
     }
 
+    public Map<String, Object> forbiddenMap(String k, Object v) {
+        HashMap<String, Object> map = new HashMap<>();
+        map.put("status", 403);
+        map.put(k, v);
+        return map;
+    }
+
+    private String getClientIp(HttpServletRequest request) {
+        String ip = request.getHeader("X-Forwarded-For");
+        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("X-Real-IP");
+        }
+        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getRemoteAddr();
+        }
+
+        if (ip != null && ip.contains(",")) {
+            ip = ip.split(",")[0].trim();
+        }
+        return ip;

Review Comment:
   The X-Forwarded-For header can be spoofed by clients to bypass the localhost 
restriction. An attacker could send a request with "X-Forwarded-For: 127.0.0.1" 
to gain unauthorized access to the arthasstart endpoint. For security-critical 
endpoints like this one that start diagnostic tools, you should only rely on 
request.getRemoteAddr() and not check forwarded headers, or implement 
additional authentication mechanisms.
   ```suggestion
           /*
            * For security-sensitive operations, do not trust client-controlled
            * headers such as X-Forwarded-For or X-Real-IP, since they can be
            * spoofed to bypass localhost or other IP-based restrictions.
            * Instead, rely solely on the remote address reported by the
            * servlet container.
            */
           return request.getRemoteAddr();
   ```



##########
hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/controller/PartitionAPI.java:
##########
@@ -168,27 +172,45 @@ public Map<String, Object> 
dumpPartition(@PathVariable(value = "id") int id) thr
             }
             cfIterator.close();
         });
-        return okMap("ok", null);
+        return ResponseEntity.status(HttpStatus.OK).body(okMap("ok", null));
     }
 
     /**
      * Print all keys in the partition
      */
     @GetMapping(value = "/partition/clean/{id}", produces = 
MediaType.APPLICATION_JSON_VALUE)
-    public Map<String, Object> cleanPartition(@PathVariable(value = "id") int 
id) throws
-                                                                               
   PDException {
+    public ResponseEntity<Map<String, Object>> cleanPartition(
+            @PathVariable(value = "id") int id) throws PDException {
         HgStoreEngine storeEngine = nodeService.getStoreEngine();
         BusinessHandler handler = storeEngine.getBusinessHandler();
 
         storeEngine.getPartitionEngine(id).getPartitions().forEach((graph, 
partition) -> {
             handler.cleanPartition(graph, id);
         });
-        return okMap("ok", null);
+        return ResponseEntity.status(HttpStatus.OK).body(okMap("ok", null));
     }
 
     @GetMapping(value = "/arthasstart", produces = "application/json")
-    public Map<String, Object> arthasstart(
-            @RequestParam(required = false, defaultValue = "") String flags) {
+    public ResponseEntity<Map<String, Object>> arthasstart(
+            @RequestParam(required = false, defaultValue = "") String flags,
+            HttpServletRequest request) {
+        if (request == null) {
+            log.error("Security Alert: HttpServletRequest is NULL when 
accessing /arthasstart. " +
+                      "Access denied.");
+            Map<String, Object> err = new HashMap<>();
+            err.put("status", "ERROR");
+            err.put("message", "Internal Error: Cannot determine client IP.");
+            return 
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(err);
+        }
+        String remoteAddr = getClientIp(request);
+        boolean isLocalRequest =
+                "127.0.0.1".equals(remoteAddr) || 
"[0:0:0:0:0:0:0:1]".equals(remoteAddr);

Review Comment:
   The IPv6 localhost address check is incorrect. The actual IPv6 localhost 
address returned by getRemoteAddr() is "0:0:0:0:0:0:0:1" (without brackets), 
but this code checks for "[0:0:0:0:0:0:0:1]" (with brackets). This means IPv6 
localhost requests will be incorrectly blocked. Change the check to use 
"0:0:0:0:0:0:0:1" without brackets, or alternatively use "::1" which is the 
standard IPv6 localhost representation.
   ```suggestion
                   "127.0.0.1".equals(remoteAddr) ||
                   "0:0:0:0:0:0:0:1".equals(remoteAddr) ||
                   "::1".equals(remoteAddr);
   ```



##########
hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/controller/PartitionAPI.java:
##########
@@ -168,27 +172,45 @@ public Map<String, Object> 
dumpPartition(@PathVariable(value = "id") int id) thr
             }
             cfIterator.close();
         });
-        return okMap("ok", null);
+        return ResponseEntity.status(HttpStatus.OK).body(okMap("ok", null));
     }
 
     /**
      * Print all keys in the partition
      */
     @GetMapping(value = "/partition/clean/{id}", produces = 
MediaType.APPLICATION_JSON_VALUE)
-    public Map<String, Object> cleanPartition(@PathVariable(value = "id") int 
id) throws
-                                                                               
   PDException {
+    public ResponseEntity<Map<String, Object>> cleanPartition(
+            @PathVariable(value = "id") int id) throws PDException {
         HgStoreEngine storeEngine = nodeService.getStoreEngine();
         BusinessHandler handler = storeEngine.getBusinessHandler();
 
         storeEngine.getPartitionEngine(id).getPartitions().forEach((graph, 
partition) -> {
             handler.cleanPartition(graph, id);
         });
-        return okMap("ok", null);
+        return ResponseEntity.status(HttpStatus.OK).body(okMap("ok", null));
     }
 
     @GetMapping(value = "/arthasstart", produces = "application/json")
-    public Map<String, Object> arthasstart(
-            @RequestParam(required = false, defaultValue = "") String flags) {
+    public ResponseEntity<Map<String, Object>> arthasstart(
+            @RequestParam(required = false, defaultValue = "") String flags,
+            HttpServletRequest request) {
+        if (request == null) {
+            log.error("Security Alert: HttpServletRequest is NULL when 
accessing /arthasstart. " +
+                      "Access denied.");
+            Map<String, Object> err = new HashMap<>();
+            err.put("status", "ERROR");
+            err.put("message", "Internal Error: Cannot determine client IP.");
+            return 
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(err);
+        }

Review Comment:
   The HttpServletRequest null check is unnecessary in a Spring MVC controller. 
Spring will never inject a null HttpServletRequest in a properly configured 
application. If this null check is for defensive programming, it should be 
documented why this unusual case is being handled, otherwise it can be removed 
to simplify the code.
   ```suggestion
   
   ```



##########
hugegraph-server/hugegraph-dist/src/assembly/static/conf/rest-server.properties:
##########
@@ -12,10 +12,10 @@ batch.max_write_ratio=80
 batch.max_write_threads=0
 
 # configuration of arthas
-arthas.telnet_port=8562
-arthas.http_port=8561
+arthas.telnetPort=8562
+arthas.httpPort=8561
 arthas.ip=127.0.0.1
-arthas.disabled_commands=jad
+arthas.disabledCommands=jad,ognl,vmtool

Review Comment:
   The naming pattern inconsistency fix is incomplete. The docker configuration 
files still use the old underscore naming pattern (arthas.telnet_port, 
arthas.http_port, arthas.disabled_commands) instead of the new camelCase 
pattern. These files need to be updated to use arthas.telnetPort, 
arthas.httpPort, and arthas.disabledCommands to be consistent with the changes 
in the main configuration files.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to