Files
codeql/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlinkGood.go
2022-05-20 10:07:19 -07:00

81 lines
2.0 KiB
Go

package main
import (
"archive/tar"
"archive/zip"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
)
func isRelGood(candidate, target string) bool {
// GOOD: resolves all symbolic links before checking
// that `candidate` does not escape from `target`
if filepath.IsAbs(candidate) {
return false
}
realpath, err := filepath.EvalSymlinks(filepath.Join(target, candidate))
if err != nil {
return false
}
relpath, err := filepath.Rel(target, realpath)
return err == nil && !strings.HasPrefix(filepath.Clean(relpath), "..")
}
func unzipSymlinkGood(f io.Reader, target string) {
r := tar.NewReader(f)
for {
header, err := r.Next()
if err != nil {
break
}
if isRelGood(header.Linkname, target) && isRelGood(header.Name, target) {
os.Symlink(header.Linkname, header.Name)
}
}
}
func unzipSymlinkGoodZip(f io.ReaderAt, target string) {
r, _ := zip.NewReader(f, 100)
for _, header := range r.File {
linkData, _ := header.Open()
linkNameBytes, _ := ioutil.ReadAll(linkData)
linkName := string(linkNameBytes)
if isRelGood(linkName, target) && isRelGood(header.Name, target) {
os.Symlink(linkName, header.Name)
}
}
}
func isRelGoodReadlink(candidate, target string) bool {
// GOOD: resolves symbolic links before checking
// that `candidate` does not escape from `target`.
// Note this is not actually safe (using Readlink
// to resolve everything is not simple), so I just
// make some token use of it here.
if filepath.IsAbs(candidate) {
return false
}
realpath, err := os.Readlink(filepath.Join(target, candidate))
if err != nil {
return false
}
relpath, err := filepath.Rel(target, realpath)
return err == nil && !strings.HasPrefix(filepath.Clean(relpath), "..")
}
func unzipSymlinkGoodReadlink(f io.Reader, target string) {
r := tar.NewReader(f)
for {
header, err := r.Next()
if err != nil {
break
}
if isRelGoodReadlink(header.Linkname, target) && isRelGoodReadlink(header.Name, target) {
os.Symlink(header.Linkname, header.Name)
}
}
}