-
-
Notifications
You must be signed in to change notification settings - Fork 397
[sec] check if symlink points outside of destination directory #242
Description
I was able to confirm that os.Create() will happily follow symlinks.
Although standard tools like tar will not likely allow you to add two files with the same name to an archive file, it's certainly easy enough to do in code. This means that we need to add an additional check before writing to a destination to make sure that it's not a symlink outside of the destination.
The vulnerability only exists if OverwriteExisting is also turned on.
What file is affected?
filecompressor.go:
// DecompressFile reads the source file and decompresses it to destination.
func (fc FileCompressor) DecompressFile(source, destination string) error {
if fc.Decompressor == nil {
return fmt.Errorf("no decompressor specified")
}
if !fc.OverwriteExisting && fileExists(destination) {
return fmt.Errorf("file exists: %s", destination)
}
// TODO needs check here
in, err := os.Open(source)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(destination)
if err != nil {
return err
}
defer out.Close()
return fc.Decompress(in, out)
}Possible solution
If the destination exists we should always check if it's a symlink first:
if fileExists(destination) {
// TODO check if destination is a symlink with an outside target
// should be a simple os.Lstat()
if !fc.OverwriteExisting {
return fmt.Errorf("file exists: %s", destination)
}
}Also, we could block ALL symilnks that have a target outside of the destination directory.
I think the former approach is the best for now, as some archives may link outside of the destination directory for legitimate reasons.
Please link to any related issues, pull requests, and/or discussion
This is related to