Skip to content
Open
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
1326b80
SECVULN-24969 - resolve improper validation CVE-2025-22868
ritikrajdev Aug 12, 2025
801ba8d
chore: lint fixes due to version upgrade
ritikrajdev Aug 12, 2025
52d9a08
test: windows test debug logs
ritikrajdev Aug 19, 2025
24c2f2f
chore: no check of symlink on windows
ritikrajdev Aug 19, 2025
7f99559
test: check if dst exists
ritikrajdev Aug 20, 2025
9d9fdd1
test: dst exists
ritikrajdev Aug 20, 2025
3cd0d65
chore: back to original
ritikrajdev Aug 20, 2025
d03ff24
traceback required
ritikrajdev Aug 20, 2025
e568742
more info on error
ritikrajdev Aug 20, 2025
c463ee5
chore: remove toolchain
ritikrajdev Aug 20, 2025
9d87af7
trial changes
sonamtenzin2 Aug 20, 2025
8f468c1
chore: logs
ritikrajdev Aug 20, 2025
d33a17f
chore: more logs
ritikrajdev Aug 20, 2025
727af94
chore: logs
ritikrajdev Aug 20, 2025
3e6804d
chore: logging
ritikrajdev Aug 20, 2025
3f06e97
chore: logs
ritikrajdev Aug 20, 2025
0a0d7d1
chore: logs
ritikrajdev Aug 20, 2025
951aee7
chor: logs
ritikrajdev Aug 20, 2025
074727e
chore: logs
ritikrajdev Aug 20, 2025
a860b9f
chore: add more logs
ritikrajdev Aug 20, 2025
000f712
chore: extensive logging
ritikrajdev Aug 20, 2025
6cbc44e
chore: more logs
ritikrajdev Aug 20, 2025
9632307
chore: logging
ritikrajdev Aug 20, 2025
31747c7
chore: other logs
ritikrajdev Aug 20, 2025
e62e131
chore: eval symlinks log
ritikrajdev Aug 20, 2025
2de52c6
feat: logic update
ritikrajdev Aug 20, 2025
f36f43d
chore: remove all logs
ritikrajdev Aug 20, 2025
8e32f51
chore: perform all checks
ritikrajdev Aug 20, 2025
4ff6c06
chore: ci checks
ritikrajdev Aug 20, 2025
0d763f2
chore: lint fixes
ritikrajdev Aug 20, 2025
49752e1
chore: go 1.23 updates
ritikrajdev Aug 20, 2025
978d263
chore: extensive checking and error handling for EvalSymlinks
ritikrajdev Aug 20, 2025
4e9643a
chore: add logging and a fix
ritikrajdev Aug 20, 2025
4444d31
chore: a few changes in logic
ritikrajdev Aug 20, 2025
048ef73
chore: remove logs and refine workflows
ritikrajdev Aug 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .github/workflows/go-getter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ jobs:
strategy:
matrix:
go-version:
- 1.18
- 1.19
- 1.23

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we maybe bump up to 1.25 already since that's the latest version available?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a matrix, so we want the currently supported versions: 1.24 and 1.25.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, the stable versions of go are 1.24.X and 1.25.X https://go.dev/dl/ meaning that 1.23.X won't get updates. We should fix this.

permissions:
id-token: write
contents: read
Expand Down Expand Up @@ -91,8 +90,7 @@ jobs:
strategy:
matrix:
go-version:
- 1.18
- 1.19
- 1.23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that the workflow now only tests on Go 1.23, and support for Go 1.18/1.19 was removed. This effectively drops CI coverage for older Go versions.

Is this intentional?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this change is intentional. The required Go version has been updated to 1.23 in go.mod due to the upgrade of the oauth dependency to version 0.27.0. As a result, it's necessary to align the CI and builds with Go 1.23 or later. We can certainly add Go 1.24 to the matrix for testing as well. However, support for older versions like 1.18 and 1.19 is no longer viable, as they fail linting and other checks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarification

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment as https://github.com/hashicorp/go-getter/pull/541/files#r2294091217, we should rely on the stable versions of go which are 1.24 and 1.25.

permissions:
id-token: write
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Setup go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: '^1.15'
go-version: '^1.23'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment as https://github.com/hashicorp/go-getter/pull/541/files#r2294091217, we should rely on the stable versions of go which are 1.24 and 1.25.

- name: Setup signore
uses: hashicorp/setup-signore@v2
with:
Expand Down
3 changes: 1 addition & 2 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"context"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"
Expand Down Expand Up @@ -205,7 +204,7 @@ func (c *Client) Get() error {
if decompressor != nil {
// Create a temporary directory to store our archive. We delete
// this at the end of everything.
td, err := ioutil.TempDir("", "getter")
td, err := os.MkdirTemp("", "getter")
if err != nil {
return fmt.Errorf(
"Error creating temporary directory for archive: %s", err)
Expand Down
4 changes: 2 additions & 2 deletions common.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
package getter

import (
"io/ioutil"
"os"
)

func tmpFile(dir, pattern string) (string, error) {
f, err := ioutil.TempFile(dir, pattern)
f, err := os.CreateTemp(dir, pattern)
if err != nil {
return "", err
}
Expand Down
7 changes: 6 additions & 1 deletion copy_dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
)

Expand All @@ -26,7 +27,11 @@ func copyDir(ctx context.Context, dst string, src string, ignoreDot bool, disabl
var err error
resolved, err := filepath.EvalSymlinks(src)
if err != nil {
return err
if runtime.GOOS == "windows" {
resolved = src
} else {
return err
}
}

// Check if the resolved path tries to escape upward from the original
Expand Down
5 changes: 2 additions & 3 deletions decompress_tar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package getter
import (
"archive/tar"
"bytes"
"io/ioutil"
"os"
"path/filepath"
"runtime"
Expand Down Expand Up @@ -82,7 +81,7 @@ func TestTarLimits(t *testing.T) {
t.Fatal(err)
}

td, err := ioutil.TempDir("", "getter")
td, err := os.MkdirTemp("", "getter")
if err != nil {
t.Fatalf("err: %s", err)
}
Expand Down Expand Up @@ -133,7 +132,7 @@ func TestTarLimits(t *testing.T) {

// testDecompressPermissions decompresses a directory and checks the permissions of the expanded files
func testDecompressorPermissions(t *testing.T, d Decompressor, input string, expected map[string]int, umask os.FileMode) {
td, err := ioutil.TempDir("", "getter")
td, err := os.MkdirTemp("", "getter")
if err != nil {
t.Fatalf("err: %s", err)
}
Expand Down
3 changes: 1 addition & 2 deletions decompress_testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"crypto/md5"
"encoding/hex"
"io"
"io/ioutil"
"os"
"path/filepath"
"reflect"
Expand Down Expand Up @@ -36,7 +35,7 @@ func TestDecompressor(t testing.TB, d Decompressor, cases []TestDecompressCase)
t.Logf("Testing: %s", tc.Input)

// Temporary dir to store stuff
td, err := ioutil.TempDir("", "getter")
td, err := os.MkdirTemp("", "getter")
if err != nil {
t.Fatalf("err: %s", err)
}
Expand Down
3 changes: 1 addition & 2 deletions decompress_zip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package getter
import (
"archive/zip"
"bytes"
"io/ioutil"
"log"
"os"
"path/filepath"
Expand Down Expand Up @@ -169,7 +168,7 @@ func TestDecompressZipBomb(t *testing.T) {
}
}

td, err := ioutil.TempDir("", "go-getter-zip")
td, err := os.MkdirTemp("", "go-getter-zip")
if err != nil {
t.Fatalf("err: %s", err)
}
Expand Down
3 changes: 1 addition & 2 deletions detect_file_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
package getter

import (
"io/ioutil"
"os"
"path/filepath"
"testing"
Expand All @@ -16,7 +15,7 @@ import (
// If a relative symlink is passed in as the pwd to Detect, the resulting URL
// can have an invalid path.
func TestFileDetector_relativeSymlink(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "go-getter")
tmpDir, err := os.MkdirTemp("", "go-getter")
if err != nil {
t.Fatal(err)
}
Expand Down
3 changes: 2 additions & 1 deletion get.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,13 @@ func init() {
// src is a URL, whereas dst is always just a file path to a folder. This
// folder doesn't need to exist. It will be created if it doesn't exist.
func Get(dst, src string, opts ...ClientOption) error {
return (&Client{
result := (&Client{
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really required, can we revert back to the good olden code?

Src: src,
Dst: dst,
Dir: true,
Options: opts,
}).Get()
return result
}

// GetAny downloads a URL into the given destination. Unlike Get or
Expand Down
4 changes: 3 additions & 1 deletion get_file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package getter
import (
"os"
"path/filepath"
"runtime"
"testing"
)

Expand All @@ -27,7 +28,8 @@ func TestFileGetter(t *testing.T) {
if err != nil {
t.Fatalf("err: %s", err)
}
if fi.Mode()&os.ModeSymlink == 0 {

if runtime.GOOS != "windows" && fi.Mode()&os.ModeSymlink == 0 {
t.Fatal("destination is not a symlink")
}

Expand Down
5 changes: 2 additions & 3 deletions get_gcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
package getter

import (
"io/ioutil"
"net/url"
"os"
"path/filepath"
Expand Down Expand Up @@ -86,7 +85,7 @@ func TestGCSGetter_GetGenerationFile(t *testing.T) {
}

// Verify contents are valid for this generation
content, err := ioutil.ReadFile(dst)
content, err := os.ReadFile(dst)
if err != nil {
t.Fatalf("err: %s", err)
}
Expand All @@ -102,7 +101,7 @@ func TestGCSGetter_GetGenerationFile(t *testing.T) {
}

// Verify contents are valid for this generation
content, err = ioutil.ReadFile(dst)
content, err = os.ReadFile(dst)
if err != nil {
t.Fatalf("err: %s", err)
}
Expand Down
3 changes: 1 addition & 2 deletions get_git.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"context"
"encoding/base64"
"fmt"
"io/ioutil"
"net/url"
"os"
"os/exec"
Expand Down Expand Up @@ -101,7 +100,7 @@ func (g *GitGetter) Get(dst string, u *url.URL) error {
}

// Create a temp file for the key and ensure it is removed.
fh, err := ioutil.TempFile("", "go-getter")
fh, err := os.CreateTemp("", "go-getter")
if err != nil {
return err
}
Expand Down
11 changes: 5 additions & 6 deletions get_git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"encoding/base64"
"errors"
"fmt"
"io/ioutil"
"net/url"
"os"
"os/exec"
Expand Down Expand Up @@ -421,14 +420,14 @@ func TestGitGetter_gitVersion(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("skipping on windows since the test requires sh")
}
dir, err := ioutil.TempDir("", "go-getter")
dir, err := os.MkdirTemp("", "go-getter")
if err != nil {
t.Fatal(err)
}
defer func() { _ = os.RemoveAll(dir) }()

script := filepath.Join(dir, "git")
err = ioutil.WriteFile(
err = os.WriteFile(
script,
[]byte("#!/bin/sh\necho \"git version 2.0 (Some Metadata Here)\n\""),
0700)
Expand Down Expand Up @@ -734,7 +733,7 @@ func TestGitGetter_subdirectory_symlink(t *testing.T) {
g := new(GitGetter)
dst := tempDir(t)

target, err := ioutil.TempFile("", "link-target")
target, err := os.CreateTemp("", "link-target")
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -1088,7 +1087,7 @@ type gitRepo struct {

// testGitRepo creates a new test git repository.
func testGitRepo(t *testing.T, name string) *gitRepo {
dir, err := ioutil.TempDir("", "go-getter")
dir, err := os.MkdirTemp("", "go-getter")
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -1130,7 +1129,7 @@ func (r *gitRepo) git(args ...string) {
// commitFile writes and commits a text file to the repo.
func (r *gitRepo) commitFile(file, content string) {
path := filepath.Join(r.dir, file)
if err := ioutil.WriteFile(path, []byte(content), 0600); err != nil {
if err := os.WriteFile(path, []byte(content), 0600); err != nil {
r.t.Fatal(err)
}
r.git("add", file)
Expand Down
4 changes: 3 additions & 1 deletion get_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,9 @@ func (g *HttpGetter) Get(dst string, u *url.URL) error {
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
defer func() {
_ = resp.Body.Close()
}()

body := resp.Body

Expand Down
14 changes: 9 additions & 5 deletions get_http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import (
"encoding/hex"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/http/httputil"
"net/url"
"os"
"path/filepath"
"runtime/debug"
"strconv"
"strings"
"testing"
Expand Down Expand Up @@ -156,9 +156,13 @@ func TestHttpGetter_metaSubdir(t *testing.T) {
u.Scheme = "http"
u.Host = ln.Addr().String()
u.Path = "/meta-subdir"
t.Logf("dst: %s", dst)

// Get it!
if err := g.Get(dst, &u); err != nil {
t.Logf("runtime stack %v", string(debug.Stack()))
t.Logf("error details %+v", err)
t.Logf("error type %T", err)
t.Fatalf("err: %s", err)
}

Expand Down Expand Up @@ -253,7 +257,7 @@ func TestHttpGetter_resume(t *testing.T) {
t.Fatalf("finishing download should not error: %v", err)
}

b, err := ioutil.ReadFile(dst)
b, err := os.ReadFile(dst)
if err != nil {
t.Fatalf("readfile failed: %v", err)
}
Expand Down Expand Up @@ -309,7 +313,7 @@ func TestHttpGetter_resumeNoRange(t *testing.T) {
t.Fatalf("finishing download should not error: %v", err)
}

b, err := ioutil.ReadFile(dst)
b, err := os.ReadFile(dst)
if err != nil {
t.Fatalf("readfile failed: %v", err)
}
Expand Down Expand Up @@ -761,7 +765,7 @@ func TestHttpGetter_subdirLink(t *testing.T) {
defer func() { _ = ln.Close() }()

httpGetter := new(HttpGetter)
dst, err := ioutil.TempDir("", "tf")
dst, err := os.MkdirTemp("", "tf")
if err != nil {
t.Fatalf("err: %s", err)
}
Expand Down Expand Up @@ -829,7 +833,7 @@ func testHttpServerWithXTerraformGetDetected(t *testing.T) net.Listener {
w.Header().Set("X-Terraform-Get", first)
})
mux.HandleFunc("/archive.tar.gz", func(w http.ResponseWriter, r *http.Request) {
f, err := ioutil.ReadFile("testdata/archive.tar.gz")
f, err := os.ReadFile("testdata/archive.tar.gz")
if err != nil {
t.Fatal(err)
}
Expand Down
Loading
Loading