cli/pkg/cmd/run/download/zip_test.go
Andy Feller cdfc12caf5 Expand logic and tests to handle edge cases
This commit expands filepathDescendsFrom(string, string) to handle edge cases such as mixing absolute and relative paths or artifact name edge cases.

Additionally, tests for filepathDescendsFrom() and downloadrun() have been expanded to verify additional use cases.
2024-11-22 15:26:11 -05:00

221 lines
4.5 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()
extractPath := filepath.Join(tmpDir, "artifact")
zipFile, err := zip.OpenReader("./fixtures/myproject.zip")
require.NoError(t, err)
defer zipFile.Close()
err = extractZip(&zipFile.Reader, extractPath)
require.NoError(t, err)
_, err = os.Stat(filepath.Join(extractPath, "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,
},
{
name: "deny parent directory filename (`..`) escaping absolute directory",
args: args{
p: filepath.FromSlash(".."),
dir: filepath.FromSlash("/var/logs/"),
},
want: false,
},
{
name: "deny parent directory filename (`..`) escaping current directory",
args: args{
p: filepath.FromSlash(".."),
dir: filepath.FromSlash("."),
},
want: false,
},
{
name: "deny parent directory filename (`..`) escaping parent directory",
args: args{
p: filepath.FromSlash(".."),
dir: filepath.FromSlash(".."),
},
want: false,
},
{
name: "deny parent directory filename (`..`) escaping relative directory",
args: args{
p: filepath.FromSlash(".."),
dir: filepath.FromSlash("relative-dir"),
},
want: false,
},
{
name: "deny current directory filename (`.`) in absolute directory",
args: args{
p: filepath.FromSlash("."),
dir: filepath.FromSlash("/var/logs/"),
},
want: false,
},
{
name: "deny current directory filename (`.`) in current directory",
args: args{
p: filepath.FromSlash("."),
dir: filepath.FromSlash("."),
},
want: false,
},
{
name: "deny current directory filename (`.`) in parent directory",
args: args{
p: filepath.FromSlash("."),
dir: filepath.FromSlash(".."),
},
want: false,
},
{
name: "deny current directory filename (`.`) in relative directory",
args: args{
p: filepath.FromSlash("."),
dir: filepath.FromSlash("relative-dir"),
},
want: false,
},
{
name: "relative path, absolute dir",
args: args{
p: filepath.FromSlash("whatever"),
dir: filepath.FromSlash("/a/b/c"),
},
want: false,
},
{
name: "absolute path, relative dir",
args: args{
p: filepath.FromSlash("/a/b/c"),
dir: filepath.FromSlash("whatever"),
},
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)
}
})
}
}