Skip to content

Commit

Permalink
subpath check
Browse files Browse the repository at this point in the history
  • Loading branch information
nothub committed Feb 2, 2023
1 parent a1f424b commit 5ce20fb
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 6 deletions.
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ var rootCmd = &cobra.Command{
for _, file := range index.Files {
ok, err := util.PathIsSubpath(file.Path, serverDir)
if err != nil {
log.Println(err)
log.Println(err.Error())
}
if err != nil || !ok {
log.Fatalln("File path is not safe: " + file.Path)
Expand Down
2 changes: 1 addition & 1 deletion cmd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ var updateCmd = &cobra.Command{
for path, _ := range newModPackInfo.File {
ok, err := util.PathIsSubpath(string(path), serverDir)
if err != nil {
log.Println(err)
log.Println(err.Error())
}
if err != nil || !ok {
log.Fatalln("File path is not safe: " + path)
Expand Down
29 changes: 25 additions & 4 deletions util/file.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package util

import (
"errors"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -31,18 +32,38 @@ func PathIsDir(path string) bool {
return info.Mode().IsDir()
}

func PathIsSubpath(path string, basePath string) (bool, error) {
absBasePath, err := filepath.Abs(basePath)
func ResolvePath(path string) (string, error) {
// resolve absolute path
path, err := filepath.Abs(path)
if err != nil {
return "", err
}

if _, err := os.Stat(path); err == nil {
// resolve symlinks
path, err = filepath.EvalSymlinks(path)
if err != nil {
return "", err
}
} else if !errors.Is(err, os.ErrNotExist) {
return "", err
}

return path, nil
}

func PathIsSubpath(subPath string, basePath string) (bool, error) {
subPath, err := ResolvePath(subPath)
if err != nil {
return false, err
}

_, err = filepath.Rel(absBasePath, path)
basePath, err = ResolvePath(basePath)
if err != nil {
return false, err
}

return true, nil
return strings.HasPrefix(subPath, basePath), nil
}

func FileDetection(hash string, path string) DetectType {
Expand Down
32 changes: 32 additions & 0 deletions util/file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package util

import (
"testing"
)

func testPathIsSubpath(t *testing.T, path string, basePath string) bool {
ok, err := PathIsSubpath(path, basePath)
if err != nil {
t.Log(err)
}
t.Logf("subpath=%-5v path=%s base=%s", ok, path, basePath)
return ok
}

func TestPathTraversalAbsolute(t *testing.T) {
if testPathIsSubpath(t, "/bin/file", "/tmp/") {
t.FailNow()
}
if !testPathIsSubpath(t, "/tmp/file", "/tmp/") {
t.FailNow()
}
}

func TestPathTraversalRelative(t *testing.T) {
if testPathIsSubpath(t, "../../../../../../../bin/file", "/tmp/") {
t.FailNow()
}
if !testPathIsSubpath(t, "../../../../../../../tmp/file", "/tmp/") {
t.FailNow()
}
}

0 comments on commit 5ce20fb

Please sign in to comment.