github.com/argoproj/argo-cd/v3@v3.2.1/util/security/path_traversal.go (about)

     1  package security
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  	"strings"
     7  )
     8  
     9  // Ensure that `requestedPath` is on the same directory or any subdirectory of `currentRoot`. Both `currentRoot` and
    10  // `requestedPath` must be absolute paths. They may contain any number of `./` or `/../` dir changes.
    11  func EnforceToCurrentRoot(currentRoot, requestedPath string) (string, error) {
    12  	currentRoot = filepath.Clean(currentRoot)
    13  	requestedDir, requestedFile := parsePath(requestedPath)
    14  	if !isRequestedDirUnderCurrentRoot(currentRoot, requestedDir) {
    15  		return "", fmt.Errorf("requested path %s should be on or under current directory %s", requestedPath, currentRoot)
    16  	}
    17  	return requestedDir + string(filepath.Separator) + requestedFile, nil
    18  }
    19  
    20  func isRequestedDirUnderCurrentRoot(currentRoot, requestedPath string) bool {
    21  	if currentRoot == string(filepath.Separator) {
    22  		return true
    23  	} else if currentRoot == requestedPath {
    24  		return true
    25  	}
    26  	if requestedPath[len(requestedPath)-1] != '/' {
    27  		requestedPath = requestedPath + "/"
    28  	}
    29  	if currentRoot[len(currentRoot)-1] != '/' {
    30  		currentRoot = currentRoot + "/"
    31  	}
    32  	return strings.HasPrefix(requestedPath, currentRoot)
    33  }
    34  
    35  func parsePath(path string) (string, string) {
    36  	directory := filepath.Dir(path)
    37  	if directory == path {
    38  		return directory, ""
    39  	}
    40  	return directory, filepath.Base(path)
    41  }