Skip to content

Commit

Permalink
[path] Added method 'JoinSecure' - more secure alternative to standar…
Browse files Browse the repository at this point in the history
…d 'Join'
  • Loading branch information
andyone committed May 5, 2023
1 parent d23ee0f commit 97da934
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 7 deletions.
14 changes: 9 additions & 5 deletions path/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,19 +112,23 @@ func Join(elem ...string) string {
// JoinSecure joins all elements of path, makes lexical processing, and evaluating all symlinks.
// Method returns error if final destination is not a child path of root.
func JoinSecure(root string, elem ...string) (string, error) {
var err error
result, err := filepath.EvalSymlinks(root)

result := root
if err != nil {
result = root
} else {
root = result
}

for _, e := range elem {
result = Clean(result + "/" + e)

if isLink(result) {
result, err = filepath.EvalSymlinks(result)
}

if err != nil {
return "", fmt.Errorf("Can't eval symlinks: %w", err)
if err != nil {
return "", fmt.Errorf("Can't eval symlinks: %w", err)
}
}
}

Expand Down
13 changes: 11 additions & 2 deletions path/path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,24 @@ func (s *PathUtilSuite) TestJoinSecure(c *C) {
c.Assert(err, IsNil)
c.Assert(p, Equals, "/etc/myapp/global.cfg")

testDir := c.MkDir()
p, err = JoinSecure("/unknown", "myapp/config/../global.cfg")
c.Assert(err, IsNil)
c.Assert(p, Equals, "/unknown/myapp/global.cfg")

tmpDir := c.MkDir()
os.Mkdir(tmpDir+"/test", 0755)
os.Symlink(tmpDir+"/test", tmpDir+"/testlink")
testDir := tmpDir + "/testlink"

os.Symlink(testDir+"/test.log", testDir+"/test1.link")
os.WriteFile(testDir+"/test.log", []byte("\n"), 0644)
os.Symlink(testDir+"/test.log", testDir+"/test1.link")
os.Symlink("/etc", testDir+"/test2.link")
os.Symlink(testDir+"/test3.link", testDir+"/test3.link")

p, err = JoinSecure(testDir, "mytest/../test1.link")
c.Assert(err, IsNil)
c.Assert(p, Equals, testDir+"/test.log")
c.Assert(p, Equals, tmpDir+"/test/test.log")

p, err = JoinSecure(testDir, "mytest/../test2.link")
c.Assert(err, NotNil)
Expand Down

0 comments on commit 97da934

Please sign in to comment.