Просмотр исходного кода

fix(xray): confine log.access/error to the panel log folder

An authenticated admin could set xrayTemplateConfig.log.access/error to an
arbitrary path (via the raw Xray editor or a wholesale DB import), making the
supervised Xray process write its log there — an arbitrary file write as the
Xray user (root in many deployments). resolveXrayLogPaths now reduces any log
path to its base filename under config.GetLogFolder(), so absolute paths and
".." traversal can no longer escape the log folder; "" and "none" still
disable logging.
MHSanaei 1 день назад
Родитель
Сommit
80e168787e
1 измененных файлов с 6 добавлено и 16 удалено
  1. 6 16
      internal/web/service/xray.go

+ 6 - 16
internal/web/service/xray.go

@@ -3,6 +3,7 @@ package service
 import (
 	"encoding/json"
 	"errors"
+	"path"
 	"path/filepath"
 	"runtime"
 	"strings"
@@ -498,11 +499,6 @@ func ensureStatsPolicy(policy json_util.RawMessage) json_util.RawMessage {
 	return out
 }
 
-// resolveXrayLogPaths rewrites relative `log.access` / `log.error` values to
-// absolute paths under config.GetLogFolder(), so Xray writes those files
-// alongside the panel's other logs regardless of the working directory the
-// panel was launched from. Values that are empty, "none", or already absolute
-// are left untouched, as are unparseable log blocks.
 func resolveXrayLogPaths(logCfg json_util.RawMessage) json_util.RawMessage {
 	if len(logCfg) == 0 {
 		return logCfg
@@ -521,21 +517,15 @@ func resolveXrayLogPaths(logCfg json_util.RawMessage) json_util.RawMessage {
 		if trimmed == "" || strings.EqualFold(trimmed, "none") {
 			continue
 		}
-		if filepath.IsAbs(trimmed) {
+		base := path.Base(filepath.ToSlash(trimmed))
+		if base == "" || base == "." || base == ".." || base == "/" {
 			continue
 		}
-		cleaned := filepath.ToSlash(filepath.Clean(trimmed))
-		base := filepath.Base(cleaned)
-		if base == "" || base == "." || base == string(filepath.Separator) {
+		confined := filepath.Join(config.GetLogFolder(), base)
+		if confined == trimmed {
 			continue
 		}
-		// Only rewrite bare names ("./access.log", "access.log").
-		// A nested relative path like "./logs/foo.log" is treated as
-		// a deliberate user choice and left alone.
-		if cleaned != base {
-			continue
-		}
-		parsed[key] = filepath.Join(config.GetLogFolder(), base)
+		parsed[key] = confined
 		changed = true
 	}
 	if !changed {