Our rudimentary check for whether a file path is entirely contained under a directory had a false negative when the parent directory is "/".
148 lines
2.9 KiB
Go
148 lines
2.9 KiB
Go
package download
|
|
|
|
import (
|
|
"archive/zip"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func Test_extractZip(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
wd, err := os.Getwd()
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { _ = os.Chdir(wd) })
|
|
|
|
zipFile, err := zip.OpenReader("./fixtures/myproject.zip")
|
|
require.NoError(t, err)
|
|
defer zipFile.Close()
|
|
|
|
extractPath := filepath.Join(tmpDir, "artifact")
|
|
err = os.MkdirAll(extractPath, 0700)
|
|
require.NoError(t, err)
|
|
require.NoError(t, os.Chdir(extractPath))
|
|
|
|
err = extractZip(&zipFile.Reader, ".")
|
|
require.NoError(t, err)
|
|
|
|
_, err = os.Stat(filepath.Join("src", "main.go"))
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func Test_filepathDescendsFrom(t *testing.T) {
|
|
type args struct {
|
|
p string
|
|
dir string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want bool
|
|
}{
|
|
{
|
|
name: "root child",
|
|
args: args{
|
|
p: filepath.FromSlash("/hoi.txt"),
|
|
dir: filepath.FromSlash("/"),
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "abs descendant",
|
|
args: args{
|
|
p: filepath.FromSlash("/var/logs/hoi.txt"),
|
|
dir: filepath.FromSlash("/"),
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "abs trailing slash",
|
|
args: args{
|
|
p: filepath.FromSlash("/var/logs/hoi.txt"),
|
|
dir: filepath.FromSlash("/var/logs/"),
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "abs mismatch",
|
|
args: args{
|
|
p: filepath.FromSlash("/var/logs/hoi.txt"),
|
|
dir: filepath.FromSlash("/var/pids"),
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "abs partial prefix",
|
|
args: args{
|
|
p: filepath.FromSlash("/var/logs/hoi.txt"),
|
|
dir: filepath.FromSlash("/var/log"),
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "rel child",
|
|
args: args{
|
|
p: filepath.FromSlash("hoi.txt"),
|
|
dir: filepath.FromSlash("."),
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "rel descendant",
|
|
args: args{
|
|
p: filepath.FromSlash("./log/hoi.txt"),
|
|
dir: filepath.FromSlash("."),
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "mixed rel styles",
|
|
args: args{
|
|
p: filepath.FromSlash("./log/hoi.txt"),
|
|
dir: filepath.FromSlash("log"),
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "rel clean",
|
|
args: args{
|
|
p: filepath.FromSlash("cats/../dogs/pug.txt"),
|
|
dir: filepath.FromSlash("dogs"),
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "rel mismatch",
|
|
args: args{
|
|
p: filepath.FromSlash("dogs/pug.txt"),
|
|
dir: filepath.FromSlash("dog"),
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "rel breakout",
|
|
args: args{
|
|
p: filepath.FromSlash("../escape.txt"),
|
|
dir: filepath.FromSlash("."),
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "rel sneaky breakout",
|
|
args: args{
|
|
p: filepath.FromSlash("dogs/../../escape.txt"),
|
|
dir: filepath.FromSlash("dogs"),
|
|
},
|
|
want: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := filepathDescendsFrom(tt.args.p, tt.args.dir); got != tt.want {
|
|
t.Errorf("filepathDescendsFrom() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|