mirror of
https://github.com/github/codeql.git
synced 2025-12-20 10:46:30 +01:00
81 lines
2.0 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|