// Copyright 2026 Alibaba Group // Licensed under the Apache License, Version 2.0 package localio import ( "context" "errors" "io" "net" "net/http" "net/url" "os" "path/filepath" "strings" "testing" "github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/testseam" ) type roundTripFunc func(*http.Request) (*http.Response, error) func (fn roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) { return fn(req) } type failingBody struct{} func (failingBody) Read([]byte) (int, error) { return 0, errors.New("read failed") } func (failingBody) Close() error { return nil } type coverageTempFile struct { file *os.File writeErr error syncErr error closeErr error onClose func() } func (f *coverageTempFile) Write(value []byte) (int, error) { if f.writeErr != nil { return 0, f.writeErr } return f.file.Write(value) } func (f *coverageTempFile) Name() string { return f.file.Name() } func (f *coverageTempFile) Sync() error { if f.syncErr != nil { return f.syncErr } return f.file.Sync() } func (f *coverageTempFile) Close() error { err := f.file.Close() if f.onClose != nil { f.onClose() f.onClose = nil } if f.closeErr != nil { return f.closeErr } return err } func TestCrossPlatformCoverageDownloadURLAndPublicIPPolicy(t *testing.T) { valid := []string{ "https://alidocs.dingtalk.com/file.docx", "https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/file.md", } for _, raw := range valid { if _, err := ValidateDownloadURL(raw); err != nil { t.Errorf("ValidateDownloadURL(%q): %v", raw, err) } } invalid := []string{ "http://alidocs.dingtalk.com/file.docx", "https://127.0.0.1/file.docx", "https://evil.example/file.docx", "https://oss-cn-hangzhou-internal.aliyuncs.com/file.docx", "https://user@alidocs.dingtalk.com/file.docx", "https://alidocs.dingtalk.com:8443/file.docx", } for _, raw := range invalid { if _, err := ValidateDownloadURL(raw); err == nil { t.Errorf("ValidateDownloadURL(%q) unexpectedly succeeded", raw) } } for _, raw := range []string{"127.0.0.1", "10.0.0.1", "100.64.0.1", "192.0.2.1", "198.51.100.1", "203.0.113.1", "224.0.0.1", "2001:db8::1"} { if publicIP(net.ParseIP(raw)) { t.Errorf("publicIP(%s) = true", raw) } } for _, raw := range []string{"8.8.8.8", "1.1.1.1", "2606:4700:4700::1111"} { if !publicIP(net.ParseIP(raw)) { t.Errorf("publicIP(%s) = false", raw) } } } func TestCrossPlatformCoverageOutputPathPolicy(t *testing.T) { for _, output := range []string{"", "../escape", "nested/../../escape", "/tmp/absolute", `C:\\absolute\\file`} { if err := ValidateOutput(output); err == nil { t.Errorf("ValidateOutput(%q) unexpectedly succeeded", output) } } base := t.TempDir() destination, rel, err := ResolveOutputPath(base, "nested/file.md", "https://alidocs.dingtalk.com/file.md", "") if err != nil { t.Fatal(err) } realBase, err := filepath.EvalSymlinks(base) if err != nil { t.Fatal(err) } if rel != filepath.Join("nested", "file.md") || filepath.Dir(destination) != filepath.Join(realBase, "nested") { t.Fatalf("destination=%q rel=%q", destination, rel) } if err := os.WriteFile(destination, []byte("existing"), 0o600); err != nil { t.Fatal(err) } if _, _, err := ResolveOutputPath(base, "nested/file.md", "https://alidocs.dingtalk.com/file.md", ""); err == nil || !strings.Contains(err.Error(), "LOCAL_FILE_EXISTS") { t.Fatalf("no-clobber error = %v", err) } outside := t.TempDir() link := filepath.Join(base, "outside-link") if err := os.Symlink(outside, link); err == nil { if _, _, err := ResolveOutputPath(base, "outside-link/file", "https://alidocs.dingtalk.com/file", ""); err == nil || !strings.Contains(err.Error(), "LOCAL_PATH_UNSAFE") { t.Fatalf("symlink escape error = %v", err) } } if got := SafeFilename("../evil", "https://alidocs.dingtalk.com/"); got != "evil" { t.Errorf("SafeFilename traversal basename = %q", got) } for _, name := range []string{"CON", "bad?.txt", " trailing.txt"} { if got := SafeFilename(name, "https://alidocs.dingtalk.com/"); got != "download" { t.Errorf("SafeFilename(%q) = %q", name, got) } } } func TestCrossPlatformCoverageDownloadAtomicNoClobber(t *testing.T) { base := t.TempDir() payload := "first payload" requests := 0 client := &http.Client{Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) { requests++ if req.URL.Host != "alidocs.oss-cn-zhangjiakou.aliyuncs.com" { return nil, errors.New("unexpected host") } return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader(payload)), Header: make(http.Header)}, nil })} result, err := downloadWithClient(context.Background(), "https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/file.md", DownloadOptions{ BaseDir: base, Output: "nested/result.md", }, client) if err != nil { t.Fatal(err) } if result.RelativePath != "nested/result.md" || result.SizeBytes != int64(len(payload)) { t.Fatalf("result = %#v", result) } got, err := os.ReadFile(result.AbsolutePath) if err != nil || string(got) != payload { t.Fatalf("published content = %q, err=%v", got, err) } if _, err := downloadWithClient(context.Background(), "https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/file.md", DownloadOptions{ BaseDir: base, Output: "nested/result.md", }, client); err == nil || !strings.Contains(err.Error(), "LOCAL_FILE_EXISTS") { t.Fatalf("second download error = %v", err) } if requests != 1 { t.Fatalf("existing destination performed %d network requests, want 1 total", requests) } got, err = os.ReadFile(result.AbsolutePath) if err != nil || string(got) != payload { t.Fatalf("no-clobber content = %q, err=%v", got, err) } } func TestCrossPlatformCoverageDownloadSizeLimitCleansPartialFiles(t *testing.T) { base := t.TempDir() for _, tc := range []struct { name string contentLength int64 }{ {name: "declared", contentLength: 6}, {name: "streamed", contentLength: -1}, } { t.Run(tc.name, func(t *testing.T) { client := &http.Client{Transport: roundTripFunc(func(*http.Request) (*http.Response, error) { return &http.Response{ StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader("123456")), Header: make(http.Header), ContentLength: tc.contentLength, }, nil })} output := tc.name + ".bin" if _, err := downloadWithClientLimit(context.Background(), "https://download.dingtalk.com/file.bin", DownloadOptions{ BaseDir: base, Output: output, }, client, 5); err == nil || !strings.Contains(err.Error(), "LOCAL_DOWNLOAD_TOO_LARGE") { t.Fatalf("oversized download error = %v", err) } if _, err := os.Stat(filepath.Join(base, output)); !errors.Is(err, os.ErrNotExist) { t.Fatalf("oversized destination exists: %v", err) } entries, err := os.ReadDir(base) if err != nil { t.Fatal(err) } for _, entry := range entries { if strings.HasPrefix(entry.Name(), ".dws-download-") { t.Fatalf("oversized download left temp file %q", entry.Name()) } } }) } } func TestCrossPlatformCoverageDownloadRejectsParentReplacementDuringNetwork(t *testing.T) { base := t.TempDir() parent := filepath.Join(base, "nested") if err := os.Mkdir(parent, 0o700); err != nil { t.Fatal(err) } original := filepath.Join(base, "original-parent") client := &http.Client{Transport: roundTripFunc(func(*http.Request) (*http.Response, error) { if err := os.Rename(parent, original); err != nil { t.Skipf("platform cannot replace an open directory: %v", err) } if err := os.Mkdir(parent, 0o700); err != nil { t.Fatal(err) } return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader("payload")), Header: make(http.Header)}, nil })} if _, err := downloadWithClient(context.Background(), "https://download.dingtalk.com/file.bin", DownloadOptions{ BaseDir: base, Output: "nested/result.bin", }, client); err == nil || !strings.Contains(err.Error(), "LOCAL_PATH_CHANGED") { t.Fatalf("parent replacement error = %v", err) } for _, candidate := range []string{filepath.Join(parent, "result.bin"), filepath.Join(original, "result.bin")} { if _, err := os.Stat(candidate); !errors.Is(err, os.ErrNotExist) { t.Fatalf("parent replacement wrote %q: %v", candidate, err) } } } func TestCrossPlatformCoverageDownloadRejectsParentReplacementBeforePublish(t *testing.T) { base := t.TempDir() parent := filepath.Join(base, "nested") if err := os.Mkdir(parent, 0o700); err != nil { t.Fatal(err) } original := filepath.Join(base, "original-parent") client := &http.Client{Transport: roundTripFunc(func(*http.Request) (*http.Response, error) { return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader("payload")), Header: make(http.Header)}, nil })} testseam.Swap(t, &createDownloadTemp, func(root *os.Root) (downloadTempFile, string, error) { created, name, err := createDownloadTempInRoot(root) if err != nil { return nil, "", err } return &coverageTempFile{file: created.(*os.File), onClose: func() { if renameErr := os.Rename(parent, original); renameErr != nil { t.Skipf("platform cannot replace an open directory: %v", renameErr) } if mkdirErr := os.Mkdir(parent, 0o700); mkdirErr != nil { t.Fatal(mkdirErr) } }}, name, nil }) if _, err := downloadWithClient(context.Background(), "https://download.dingtalk.com/file.bin", DownloadOptions{ BaseDir: base, Output: "nested/result.bin", }, client); err == nil || !strings.Contains(err.Error(), "LOCAL_PATH_CHANGED") { t.Fatalf("parent replacement error = %v", err) } for _, candidate := range []string{filepath.Join(parent, "result.bin"), filepath.Join(original, "result.bin")} { if _, err := os.Stat(candidate); !errors.Is(err, os.ErrNotExist) { t.Fatalf("parent replacement wrote %q: %v", candidate, err) } } } func TestCrossPlatformCoverageDownloadFailureBoundaries(t *testing.T) { base := t.TempDir() validURL := "https://download.dingtalk.com/file.bin" if _, err := Download(context.Background(), "bad", DownloadOptions{BaseDir: base, Output: "x"}); err == nil { t.Fatal("invalid URL download succeeded") } if _, err := Download(context.Background(), validURL, DownloadOptions{BaseDir: base, Output: "../x"}); err == nil { t.Fatal("unsafe output download succeeded") } clientError := &http.Client{Transport: roundTripFunc(func(*http.Request) (*http.Response, error) { return nil, errors.New("transport") })} statusClient := &http.Client{Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) { if req.Header.Get("x-test") != "ok" || req.Header.Get("") != "" { t.Errorf("headers = %#v", req.Header) } return &http.Response{StatusCode: http.StatusBadGateway, Body: io.NopCloser(strings.NewReader("backend")), Header: make(http.Header)}, nil })} bodyErrorClient := &http.Client{Transport: roundTripFunc(func(*http.Request) (*http.Response, error) { return &http.Response{StatusCode: http.StatusOK, Body: failingBody{}, Header: make(http.Header)}, nil })} if _, err := downloadWithClient(context.Background(), validURL, DownloadOptions{BaseDir: base, Output: "transport.bin"}, clientError); err == nil { t.Fatal("transport error was ignored") } if _, err := downloadWithClient(context.Background(), validURL, DownloadOptions{BaseDir: base, Output: "status.bin", Headers: map[string]string{"x-test": "ok", " ": "ignored"}}, statusClient); err == nil { t.Fatal("HTTP status error was ignored") } if _, err := downloadWithClient(context.Background(), validURL, DownloadOptions{BaseDir: base, Output: "copy.bin"}, bodyErrorClient); err == nil { t.Fatal("body read error was ignored") } okClient := &http.Client{Transport: roundTripFunc(func(*http.Request) (*http.Response, error) { return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader("payload")), Header: make(http.Header)}, nil })} for _, tc := range []struct { name string makeTemp func(*os.Root) (downloadTempFile, string, error) }{ {"create", func(*os.Root) (downloadTempFile, string, error) { return nil, "", errors.New("create") }}, {"sync", func(root *os.Root) (downloadTempFile, string, error) { created, name, err := createDownloadTempInRoot(root) if err != nil { return nil, "", err } return &coverageTempFile{file: created.(*os.File), syncErr: errors.New("sync")}, name, nil }}, {"close", func(root *os.Root) (downloadTempFile, string, error) { created, name, err := createDownloadTempInRoot(root) if err != nil { return nil, "", err } return &coverageTempFile{file: created.(*os.File), closeErr: errors.New("close")}, name, nil }}, {"publish-race", func(root *os.Root) (downloadTempFile, string, error) { created, name, err := createDownloadTempInRoot(root) if err != nil { return nil, "", err } return &coverageTempFile{file: created.(*os.File), onClose: func() { file, createErr := root.OpenFile("publish-race.bin", os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600) if createErr == nil { _ = file.Close() } }}, name, nil }}, } { t.Run(tc.name, func(t *testing.T) { testseam.Swap(t, &createDownloadTemp, tc.makeTemp) if _, err := downloadWithClient(context.Background(), validURL, DownloadOptions{BaseDir: base, Output: tc.name + ".bin"}, okClient); err == nil { t.Fatalf("%s failure was ignored", tc.name) } }) } } func TestCrossPlatformCoverageSecureHTTPClientAndFilesystemEdges(t *testing.T) { client := secureHTTPClient() transport := client.Transport.(*http.Transport) if err := client.CheckRedirect(&http.Request{URL: mustURL(t, "https://download.dingtalk.com/x")}, make([]*http.Request, 5)); err == nil { t.Fatal("redirect limit accepted") } if err := client.CheckRedirect(&http.Request{URL: mustURL(t, "https://evil.example/x")}, nil); err == nil { t.Fatal("unsafe redirect accepted") } if err := client.CheckRedirect(&http.Request{URL: mustURL(t, "https://download.dingtalk.com/x")}, nil); err != nil { t.Fatal(err) } if _, err := transport.DialContext(context.Background(), "tcp", "bad-address"); err == nil { t.Fatal("bad address dial succeeded") } t.Run("lookup error", func(t *testing.T) { testseam.Swap(t, &lookupDownloadIPs, func(context.Context, string) ([]net.IPAddr, error) { return nil, errors.New("lookup") }) if _, err := transport.DialContext(context.Background(), "tcp", "download.dingtalk.com:443"); err == nil { t.Fatal("lookup error ignored") } }) t.Run("private answer", func(t *testing.T) { testseam.Swap(t, &lookupDownloadIPs, func(context.Context, string) ([]net.IPAddr, error) { return []net.IPAddr{{IP: net.ParseIP("127.0.0.1")}}, nil }) if _, err := transport.DialContext(context.Background(), "tcp", "download.dingtalk.com:443"); err == nil { t.Fatal("private DNS answer accepted") } }) t.Run("public dial fallback and success", func(t *testing.T) { testseam.Swap(t, &lookupDownloadIPs, func(context.Context, string) ([]net.IPAddr, error) { return []net.IPAddr{{IP: net.ParseIP("8.8.8.8")}, {IP: net.ParseIP("1.1.1.1")}}, nil }) left, right := net.Pipe() t.Cleanup(func() { _ = left.Close(); _ = right.Close() }) calls := 0 testseam.Swap(t, &dialDownloadIP, func(context.Context, string, string) (net.Conn, error) { calls++ if calls == 1 { return nil, errors.New("first") } return left, nil }) if conn, err := transport.DialContext(context.Background(), "tcp", "download.dingtalk.com:443"); err != nil { t.Fatal(err) } else { _ = conn.Close() } }) t.Run("all public dials fail", func(t *testing.T) { testseam.Swap(t, &lookupDownloadIPs, func(context.Context, string) ([]net.IPAddr, error) { return []net.IPAddr{{IP: net.ParseIP("8.8.8.8")}}, nil }) testseam.Swap(t, &dialDownloadIP, func(context.Context, string, string) (net.Conn, error) { return nil, errors.New("dial") }) if _, err := transport.DialContext(context.Background(), "tcp", "download.dingtalk.com:443"); err == nil { t.Fatal("dial failure ignored") } }) base := t.TempDir() if _, _, err := ResolveOutputPath("", "default-base.tmp", "https://download.dingtalk.com/x", ""); err != nil { t.Fatal(err) } if _, _, err := ResolveOutputPath(filepath.Join(base, "missing"), "x", "https://download.dingtalk.com/x", ""); err == nil { t.Fatal("missing base succeeded") } dir := filepath.Join(base, "directory") if err := os.Mkdir(dir, 0o700); err != nil { t.Fatal(err) } for _, output := range []string{".", "directory/", "directory"} { if _, _, err := ResolveOutputPath(base, output, "https://download.dingtalk.com/path/name.txt", "preferred.txt"); err != nil { t.Errorf("directory output %q: %v", output, err) } } if _, _, err := ResolveOutputPath(base, "directory", "https://download.dingtalk.com/x", ""); err != nil { t.Fatal(err) } targetDir := filepath.Join(base, "target-dir") _ = os.Mkdir(targetDir, 0o700) if _, _, err := ResolveOutputPath(base, "target-dir", "https://download.dingtalk.com/x", "x"); err != nil { t.Fatal(err) } targetFile := filepath.Join(base, "existing.txt") _ = os.WriteFile(targetFile, []byte("x"), 0o600) if _, _, err := ResolveOutputPath(base, "existing.txt", "https://download.dingtalk.com/x", ""); err == nil || !strings.Contains(err.Error(), "LOCAL_FILE_EXISTS") { t.Fatalf("existing destination error = %v", err) } link := filepath.Join(base, "target-link") if err := os.Symlink(targetFile, link); err == nil { if _, _, err := ResolveOutputPath(base, "target-link", "https://download.dingtalk.com/x", ""); err == nil { t.Fatal("symlink destination accepted") } } fileParent := filepath.Join(base, "file-parent") _ = os.WriteFile(fileParent, []byte("x"), 0o600) if _, _, err := ResolveOutputPath(base, "file-parent/child", "https://download.dingtalk.com/x", ""); err == nil { t.Fatal("file parent accepted") } root, err := os.OpenRoot(base) if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = root.Close() }) if err := ensureSafeParent(root, "../escape"); err == nil { t.Fatal("escaping parent accepted") } if err := ensureSafeParent(root, "."); err != nil { t.Fatal(err) } source, err := root.OpenFile("source.tmp", os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600) if err != nil { t.Fatal(err) } _, _ = source.WriteString("x") _ = source.Close() destination := filepath.Join(base, "publish.txt") _ = os.WriteFile(destination, []byte("old"), 0o600) if err := publishTempFile(root, "source.tmp", "publish.txt"); err == nil { t.Fatal("publish existing destination succeeded") } if err := publishTempFile(root, "missing-source", "new.txt"); err == nil { t.Fatal("publish missing source succeeded") } symlinkDestination := filepath.Join(base, "publish-link") if err := os.Symlink(destination, symlinkDestination); err == nil { if err := publishTempFile(root, "source.tmp", "publish-link"); err == nil { t.Fatal("publish to symlink succeeded") } } closedRoot, err := os.OpenRoot(base) if err != nil { t.Fatal(err) } _ = closedRoot.Close() if _, _, err := createDownloadTempInRoot(closedRoot); err == nil { t.Fatal("temp creation in closed root succeeded") } for _, name := range []string{"", ".", "..", "name.", "name ", "bad\x00", "AUX", "COM1", "LPT9"} { _ = sanitizeFilename(name) } _ = SafeFilename("", "https://download.dingtalk.com/path/fallback.txt") _ = SafeFilename("", "https://download.dingtalk.com/%zz") _ = SafeFilename("", "://bad") _ = publicIP(net.IP{1, 2, 3}) } func TestCrossPlatformCoverageSecureHTTPClientDisablesEnvironmentProxy(t *testing.T) { t.Setenv("HTTPS_PROXY", "http://127.0.0.1:3128") transport := secureHTTPClient().Transport.(*http.Transport) if transport.Proxy != nil { t.Fatal("secure download client accepted an environment proxy") } } func TestCrossPlatformCoverageSecureHTTPClientStripsCrossOriginHeaders(t *testing.T) { client := secureHTTPClient() original := &http.Request{ URL: mustURL(t, "https://download.dingtalk.com/source"), Header: http.Header{ "X-Oss-Security-Token": []string{"credential-a"}, "X-Download-Auth": []string{"credential-b"}, }, } sameOrigin := &http.Request{ URL: mustURL(t, "https://DOWNLOAD.dingtalk.com.:443/next"), Header: original.Header.Clone(), } if err := client.CheckRedirect(sameOrigin, []*http.Request{original}); err != nil { t.Fatal(err) } if sameOrigin.Header.Get("X-Oss-Security-Token") == "" { t.Fatal("same-origin redirect unexpectedly stripped request headers") } crossOrigin := &http.Request{ URL: mustURL(t, "https://attacker-bucket.oss-cn-hangzhou.aliyuncs.com/next"), Header: original.Header.Clone(), } if err := client.CheckRedirect(crossOrigin, []*http.Request{original}); err != nil { t.Fatal(err) } if len(crossOrigin.Header) != 0 { t.Fatalf("cross-origin redirect retained %d request headers", len(crossOrigin.Header)) } multiHop := &http.Request{ URL: mustURL(t, "https://attacker-bucket.oss-cn-hangzhou.aliyuncs.com/final"), Header: original.Header.Clone(), } if err := client.CheckRedirect(multiHop, []*http.Request{original, crossOrigin}); err != nil { t.Fatal(err) } if len(multiHop.Header) != 0 { t.Fatalf("later cross-origin redirect restored %d initial request headers", len(multiHop.Header)) } } func TestCrossPlatformCoverageFilesystemInjectedFailures(t *testing.T) { base := t.TempDir() validURL := "https://download.dingtalk.com/x" cancelled, cancel := context.WithCancel(context.Background()) cancel() if _, err := Download(cancelled, validURL, DownloadOptions{BaseDir: base, Output: "default-client.bin"}); err == nil { t.Fatal("cancelled default client download succeeded") } t.Run("getwd", func(t *testing.T) { testseam.Swap(t, &localGetwd, func() (string, error) { return "", errors.New("getwd") }) _, _, _ = ResolveOutputPath("", "x", validURL, "") }) t.Run("abs", func(t *testing.T) { testseam.Swap(t, &localAbs, func(string) (string, error) { return "", errors.New("abs") }) _, _, _ = ResolveOutputPath(base, "x", validURL, "") }) t.Run("eval base", func(t *testing.T) { testseam.Swap(t, &localEvalSymlinks, func(string) (string, error) { return "", errors.New("eval") }) _, _, _ = ResolveOutputPath(base, "x", validURL, "") }) t.Run("open base", func(t *testing.T) { testseam.Swap(t, &openDownloadRoot, func(string) (*os.Root, error) { return nil, errors.New("open root") }) _, _, _ = ResolveOutputPath(base, "x", validURL, "") }) t.Run("mkdir", func(t *testing.T) { testseam.Swap(t, &downloadRootMkdir, func(*os.Root, string, os.FileMode) error { return errors.New("mkdir") }) _, _, _ = ResolveOutputPath(base, "new/target", validURL, "") }) t.Run("lstat after mkdir", func(t *testing.T) { calls := 0 testseam.Swap(t, &downloadRootLstat, func(root *os.Root, name string) (os.FileInfo, error) { if name == "new-after" { calls++ if calls > 1 { return nil, errors.New("after mkdir") } } return root.Lstat(name) }) _, _, _ = ResolveOutputPath(base, "new-after/target", validURL, "") }) t.Run("open parent", func(t *testing.T) { if err := os.Mkdir(filepath.Join(base, "open-parent"), 0o700); err != nil { t.Fatal(err) } testseam.Swap(t, &openDownloadParent, func(*os.Root, string) (*os.Root, error) { return nil, errors.New("open parent") }) _, _, _ = ResolveOutputPath(base, "open-parent/target", validURL, "") }) t.Run("parent stat", func(t *testing.T) { if err := os.Mkdir(filepath.Join(base, "parent-stat"), 0o700); err != nil { t.Fatal(err) } testseam.Swap(t, &downloadRootStat, func(root *os.Root, name string) (os.FileInfo, error) { if name == "." { return nil, errors.New("parent stat") } return root.Stat(name) }) _, _, _ = ResolveOutputPath(base, "parent-stat/target", validURL, "") }) t.Run("parent identity", func(t *testing.T) { if err := os.Mkdir(filepath.Join(base, "parent-identity"), 0o700); err != nil { t.Fatal(err) } otherInfo, err := os.Stat(t.TempDir()) if err != nil { t.Fatal(err) } testseam.Swap(t, &downloadRootStat, func(root *os.Root, name string) (os.FileInfo, error) { if name == "parent-identity" { return otherInfo, nil } return root.Stat(name) }) _, _, _ = ResolveOutputPath(base, "parent-identity/target", validURL, "") }) t.Run("destination directory", func(t *testing.T) { if err := os.Mkdir(filepath.Join(base, "destination-directory"), 0o700); err != nil { t.Fatal(err) } dirInfo, err := os.Stat(base) if err != nil { t.Fatal(err) } testseam.Swap(t, &downloadRootLstat, func(root *os.Root, name string) (os.FileInfo, error) { if name == "target" { return dirInfo, nil } return root.Lstat(name) }) _, _, _ = ResolveOutputPath(base, "destination-directory/target", validURL, "") }) t.Run("destination symlink", func(t *testing.T) { if err := os.Mkdir(filepath.Join(base, "destination-symlink"), 0o700); err != nil { t.Fatal(err) } link := filepath.Join(base, "coverage-link") if err := os.Symlink(filepath.Join(base, "destination-symlink"), link); err != nil { t.Skipf("symlink unavailable: %v", err) } linkInfo, err := os.Lstat(link) if err != nil { t.Fatal(err) } testseam.Swap(t, &downloadRootLstat, func(root *os.Root, name string) (os.FileInfo, error) { if name == "target" { return linkInfo, nil } return root.Lstat(name) }) _, _, _ = ResolveOutputPath(base, "destination-symlink/target", validURL, "") }) t.Run("destination lstat", func(t *testing.T) { if err := os.Mkdir(filepath.Join(base, "destination-lstat"), 0o700); err != nil { t.Fatal(err) } testseam.Swap(t, &downloadRootLstat, func(root *os.Root, name string) (os.FileInfo, error) { if name == "target" { return nil, errors.New("destination lstat") } return root.Lstat(name) }) _, _, _ = ResolveOutputPath(base, "destination-lstat/target", validURL, "") }) t.Run("unsafe parent type", func(t *testing.T) { filePath := filepath.Join(base, "unsafe-parent") if err := os.WriteFile(filePath, []byte("x"), 0o600); err != nil { t.Fatal(err) } root, err := os.OpenRoot(base) if err != nil { t.Fatal(err) } defer root.Close() if err := ensureSafeParent(root, "unsafe-parent"); err == nil { t.Fatal("regular file accepted as output parent") } }) t.Run("publish remove", func(t *testing.T) { root, err := os.OpenRoot(base) if err != nil { t.Fatal(err) } defer root.Close() file, err := root.OpenFile("remove-source", os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600) if err != nil { t.Fatal(err) } _ = file.Close() testseam.Swap(t, &downloadRootRemove, func(*os.Root, string) error { return errors.New("remove") }) if err := publishTempFile(root, "remove-source", "remove-destination"); err == nil { t.Fatal("publish remove error ignored") } }) } func mustURL(t *testing.T, raw string) *url.URL { t.Helper() parsed, err := url.Parse(raw) if err != nil { t.Fatal(err) } return parsed }