Skip to content

Commit b5394ea

Browse files
committed
fix: clean up linter issues
1 parent f8a2ae2 commit b5394ea

File tree

12 files changed

+141
-28
lines changed

12 files changed

+141
-28
lines changed

internal/buildinfo/parse.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func Parse(info string) ([]model.BuildInfo, error) {
2828
if !strings.HasPrefix(l, "\t") {
2929
matches := goVersionRgx.FindStringSubmatch(l)
3030
if len(matches) != 2 {
31-
return nil, fmt.Errorf("unrecognised version line: %s", l)
31+
return nil, fmt.Errorf("unrecognized version line: %s", l)
3232
}
3333
if current.Path != "" {
3434
results = append(results, current)
@@ -81,7 +81,7 @@ func Parse(info string) ([]model.BuildInfo, error) {
8181
case "":
8282
// blank (tab prefixed) lines appear after lines relating to replace directives in Go 1.18 compiled binaries
8383
default:
84-
return nil, fmt.Errorf("unrecognised line: %s", l)
84+
return nil, fmt.Errorf("unrecognized line: %s", l)
8585
}
8686
}
8787
if current.Path != "" {

internal/buildinfo/parse_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,9 @@ func TestParse(t *testing.T) {
232232
},
233233
},
234234
{
235-
name: "unrecognised line",
235+
name: "unrecognized line",
236236
input: `/tmp/lichen: invalid`,
237-
expectedErr: "unrecognised version line: /tmp/lichen: invalid",
237+
expectedErr: "unrecognized version line: /tmp/lichen: invalid",
238238
},
239239
{
240240
name: "partial path line",

internal/license/db/gen/gen.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"io"
99
"log"
10+
"log/slog"
1011
"os"
1112
)
1213

@@ -28,13 +29,22 @@ func run() error {
2829
if err != nil {
2930
return err
3031
}
31-
defer f.Close()
32+
defer func() {
33+
if err := f.Close(); err != nil {
34+
slog.Error("failed to close binary", slog.String("reason", err.Error()))
35+
}
36+
}()
3237

3338
w, err := os.Create(os.Args[2])
3439
if err != nil {
3540
return err
3641
}
37-
defer w.Close()
42+
43+
defer func() {
44+
if err := w.Close(); err != nil {
45+
slog.Error("failed to close report", slog.String("reason", err.Error()))
46+
}
47+
}()
3848

3949
buf := &bytes.Buffer{}
4050
encoder := ascii85.NewEncoder(buf)
@@ -52,7 +62,9 @@ func run() error {
5262
return err
5363
}
5464

55-
fmt.Fprintf(w, tmpl, buf.String())
65+
if _, err := fmt.Fprintf(w, tmpl, buf.String()); err != nil {
66+
slog.Error("failed to write report", slog.String("reason", err.Error()))
67+
}
5668

5769
return nil
5870
}

internal/license/resolve.go

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ package license
33
import (
44
"fmt"
55
"io/ioutil"
6+
"log/slog"
67
"path/filepath"
78
"regexp"
89
"strings"
910

1011
"github.com/google/licenseclassifier"
12+
1113
"github.com/selesy/lichen/internal/license/db"
1214
"github.com/selesy/lichen/internal/model"
1315
)
@@ -18,9 +20,15 @@ func Resolve(modules []model.Module, threshold float64) ([]model.Module, error)
1820
archiveFn := licenseclassifier.ArchiveFunc(func() ([]byte, error) {
1921
f, err := db.Open()
2022
if err != nil {
21-
return nil, fmt.Errorf("failed to open license databse: %w", err)
23+
return nil, fmt.Errorf("failed to open license database: %w", err)
2224
}
23-
defer f.Close()
25+
26+
defer func() {
27+
if err := f.Close(); err != nil {
28+
slog.Error("failed to close license database", slog.String("reason", err.Error()))
29+
}
30+
}()
31+
2432
return ioutil.ReadAll(f)
2533
})
2634

@@ -32,7 +40,7 @@ func Resolve(modules []model.Module, threshold float64) ([]model.Module, error)
3240
for i, m := range modules {
3341
if m.IsLocal() {
3442
// there is no guarantee we are being run in a location that makes local module references resolvable.. to
35-
// avoid incidental and non-obvious behaviour here, we simply don't touch such references - overrides must
43+
// avoid incidental and non-obvious behavior here, we simply don't touch such references - overrides must
3644
// be provided instead.
3745
continue
3846
}
@@ -71,6 +79,17 @@ func locateLicenses(path string) (lp []string, err error) {
7179
func classify(lc *licenseclassifier.License, paths []string) ([]model.License, error) {
7280
licenses := make([]model.License, 0)
7381
for _, p := range paths {
82+
// normalize the path
83+
p, err := filepath.Abs(p)
84+
if err != nil {
85+
return nil, err
86+
}
87+
// resolve symlinks to prevent directory traversal attacks
88+
p, err = filepath.EvalSymlinks(p)
89+
if err != nil {
90+
return nil, err
91+
}
92+
7493
content, err := ioutil.ReadFile(p)
7594
if err != nil {
7695
return nil, err

internal/model/model.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ type ModuleReference struct {
2727
}
2828

2929
// pathRgx covers
30-
// - unix paths: ".", "..", prefixed "./", prefixed "../", prefixed "/"
31-
// - windows paths: ".", "..", prefixed ".\", prefixed "..\", prefixed "<drive>:\"
30+
// - unix paths: ".", "..", prefixed "./", prefixed "../", prefixed "/"
31+
// - windows paths: ".", "..", prefixed ".\", prefixed "..\", prefixed "<drive>:\"
3232
var pathRgx = regexp.MustCompile(`^(\.\.?($|/|\\)|/|[A-Za-z]:\\)`)
3333

3434
// IsLocal returns true if the module reference points to a local path

internal/model/model_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"testing"
55

66
"github.com/stretchr/testify/assert"
7+
78
"github.com/selesy/lichen/internal/model"
89
)
910

internal/module/extract.go

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ package module
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
6-
"io/ioutil"
7+
"log/slog"
78
"os"
89
"os/exec"
10+
"path/filepath"
911

1012
"github.com/hashicorp/go-multierror"
13+
1114
"github.com/selesy/lichen/internal/buildinfo"
1215
"github.com/selesy/lichen/internal/model"
1316
)
@@ -50,20 +53,43 @@ func goVersion(ctx context.Context, paths []string) (string, error) {
5053
return "", err
5154
}
5255

53-
tempDir, err := ioutil.TempDir("", "lichen")
56+
// normalize the path
57+
goBin, err = filepath.Abs(goBin)
58+
if err != nil {
59+
return "", err
60+
}
61+
// resolve symlinks to prevent directory traversal attacks
62+
goBin, err = filepath.EvalSymlinks(goBin)
63+
if err != nil {
64+
return "", err
65+
}
66+
67+
// Validation: Ensure we actually found a 'go' binary
68+
if filepath.Base(goBin) != "go" && filepath.Base(goBin) != "go.exe" {
69+
return "", errors.New("unexpected binary resolved")
70+
}
71+
72+
tempDir, err := os.MkdirTemp("", "lichen")
5473
if err != nil {
5574
return "", fmt.Errorf("failed to create temp directory: %w", err)
5675
}
57-
defer os.Remove(tempDir)
76+
defer func() {
77+
if err := os.Remove(tempDir); err != nil {
78+
slog.Error("failed to remove temporary folder/files", slog.String("reason", err.Error()))
79+
}
80+
}()
5881

5982
args := []string{"version", "-m"}
6083
args = append(args, paths...)
6184

85+
//nolint:gosec
86+
// the goBin variable was sanitized above
6287
cmd := exec.CommandContext(ctx, goBin, args...)
6388
cmd.Dir = tempDir
6489
out, err := cmd.Output()
6590
if err != nil {
66-
if exitErr, ok := err.(*exec.ExitError); ok {
91+
exitErr := &exec.ExitError{}
92+
if errors.As(err, &exitErr) {
6793
return "", fmt.Errorf("error when running 'go version': %w - stderr: %s", err, exitErr.Stderr)
6894
}
6995
return "", fmt.Errorf("error when running 'go version': %w", err)

internal/module/fetch.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import (
77
"errors"
88
"fmt"
99
"io"
10-
"io/ioutil"
10+
"log/slog"
1111
"os"
1212
"os/exec"
13+
"path/filepath"
1314

1415
"github.com/hashicorp/go-multierror"
16+
1517
"github.com/selesy/lichen/internal/model"
1618
)
1719

@@ -25,11 +27,32 @@ func Fetch(ctx context.Context, refs []model.ModuleReference) ([]model.Module, e
2527
return nil, err
2628
}
2729

28-
tempDir, err := ioutil.TempDir("", "lichen")
30+
// normalize the path
31+
goBin, err = filepath.Abs(goBin)
32+
if err != nil {
33+
return nil, err
34+
}
35+
// resolve symlinks to prevent directory traversal attacks
36+
goBin, err = filepath.EvalSymlinks(goBin)
37+
if err != nil {
38+
return nil, err
39+
}
40+
41+
// Validation: Ensure we actually found a 'go' binary
42+
if filepath.Base(goBin) != "go" && filepath.Base(goBin) != "go.exe" {
43+
return nil, errors.New("unexpected binary resolved")
44+
}
45+
46+
tempDir, err := os.MkdirTemp("", "lichen")
2947
if err != nil {
3048
return nil, fmt.Errorf("failed to create temp directory: %w", err)
3149
}
32-
defer os.Remove(tempDir)
50+
51+
defer func() {
52+
if err := os.Remove(tempDir); err != nil {
53+
slog.Error("failed to remove temporary folder/files", slog.String("reason", err.Error()))
54+
}
55+
}()
3356

3457
args := []string{"mod", "download", "-json"}
3558
for _, ref := range refs {
@@ -38,6 +61,8 @@ func Fetch(ctx context.Context, refs []model.ModuleReference) ([]model.Module, e
3861
}
3962
}
4063

64+
//nolint:gosec
65+
// the goBin variable was sanitized above
4166
cmd := exec.CommandContext(ctx, goBin, args...)
4267
cmd.Dir = tempDir
4368
out, err := cmd.CombinedOutput()

internal/module/fetch_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"testing"
66

77
"github.com/stretchr/testify/assert"
8+
89
"github.com/selesy/lichen/internal/model"
910
"github.com/selesy/lichen/internal/module"
1011
)

internal/scan/result.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func (r EvaluatedModule) ExplainDecision() string {
3131
case DecisionNotAllowedLicenseNotPermitted:
3232
return fmt.Sprintf("not allowed - non-permitted licenses: %v", r.NotPermitted)
3333
default:
34-
panic("unrecognised decision")
34+
panic("unrecognized decision")
3535
}
3636
}
3737

@@ -52,6 +52,6 @@ func (d Decision) MarshalText() ([]byte, error) {
5252
case DecisionNotAllowedLicenseNotPermitted:
5353
return []byte("licenses-not-allowed"), nil
5454
default:
55-
panic("unrecognised decision")
55+
panic("unrecognized decision")
5656
}
5757
}

0 commit comments

Comments
 (0)