Browse Source

enhance: improve log path validation logic

Jacky 1 day ago
parent
commit
6e8099874e
3 changed files with 29 additions and 24 deletions
  1. 2 1
      .devcontainer/devcontainer.json
  2. 5 4
      internal/nginx/errors.go
  3. 22 19
      internal/nginx_log/nginx_log.go

+ 2 - 1
.devcontainer/devcontainer.json

@@ -31,7 +31,8 @@
         "ms-azuretools.vscode-docker",
         "akino.i18n-gettext",
         "github.vscode-github-actions",
-        "vue.volar"
+        "vue.volar",
+        "eamodio.gitlens"
       ]
     }
   },

+ 5 - 4
internal/nginx/errors.go

@@ -3,8 +3,9 @@ package nginx
 import "github.com/uozi-tech/cosy"
 
 var (
-	e               = cosy.NewErrorScope("nginx")
-	ErrNginx        = e.New(50000, "nginx error: {0}")
-	ErrBlockIsNil   = e.New(50001, "block is nil")
-	ErrReloadFailed = e.New(50002, "reload nginx failed: {0}")
+	e                    = cosy.NewErrorScope("nginx")
+	ErrNginx             = e.New(50000, "nginx error: {0}")
+	ErrBlockIsNil        = e.New(50001, "block is nil")
+	ErrReloadFailed      = e.New(50002, "reload nginx failed: {0}")
+	ErrNginxTOutputEmpty = e.New(50003, "nginx -T output is empty")
 )

+ 22 - 19
internal/nginx_log/nginx_log.go

@@ -118,20 +118,18 @@ func isValidLogPath(logPath string) bool {
 		return true
 	}
 
-	// If it's a symlink, follow it
+	// If it's a symlink, follow it safely
 	if fileInfo.Mode()&os.ModeSymlink != 0 {
-		linkTarget, err := os.Readlink(logPath)
+		// Use EvalSymlinks to safely resolve the entire symlink chain
+		// This function detects circular symlinks and returns an error
+		resolvedPath, err := filepath.EvalSymlinks(logPath)
 		if err != nil {
+			logger.Warn("Failed to resolve symlink (possible circular reference):", logPath, "error:", err)
 			return false
 		}
 
-		// Make the link target path absolute if it's relative
-		if !filepath.IsAbs(linkTarget) {
-			linkTarget = filepath.Join(filepath.Dir(logPath), linkTarget)
-		}
-
-		// Check the target file
-		targetInfo, err := os.Stat(linkTarget)
+		// Check the resolved target file
+		targetInfo, err := os.Stat(resolvedPath)
 		if err != nil {
 			return false
 		}
@@ -149,7 +147,12 @@ func IsLogPathUnderWhiteList(path string) bool {
 	cacheKey := fmt.Sprintf("isLogPathUnderWhiteList:%s", path)
 	res, ok := cache.Get(cacheKey)
 
-	// Deep copy the whitelist
+	// If cached, return the result directly
+	if ok {
+		return res.(bool)
+	}
+
+	// Only build the whitelist when cache miss occurs
 	logDirWhiteList := append([]string{}, settings.NginxSettings.LogDirWhiteList...)
 
 	accessLogPath := nginx.GetAccessLogPath()
@@ -165,15 +168,15 @@ func IsLogPathUnderWhiteList(path string) bool {
 		logDirWhiteList = append(logDirWhiteList, nginx.GetPrefix())
 	}
 
-	// No cache, check it
-	if !ok {
-		for _, whitePath := range logDirWhiteList {
-			if helper.IsUnderDirectory(path, whitePath) {
-				cache.Set(cacheKey, true, 0)
-				return true
-			}
+	// Check if path is under any whitelist directory
+	for _, whitePath := range logDirWhiteList {
+		if helper.IsUnderDirectory(path, whitePath) {
+			cache.Set(cacheKey, true, 0)
+			return true
 		}
-		return false
 	}
-	return res.(bool)
+
+	// Cache negative result as well to avoid repeated checks
+	cache.Set(cacheKey, false, 0)
+	return false
 }