Skip to content

Commit abe22fb

Browse files
authored
Fix all gosec security lint violations (#572)
Tighten file/directory permissions, add ReadHeaderTimeout to prevent Slowloris attacks, cap io.Copy with LimitReader for the flamegraph tar extraction, and bind the test listener to localhost instead of all interfaces. Suppress the two unavoidable G304/G107 warnings on user-provided file paths and test URLs.
1 parent 7b2fae4 commit abe22fb

File tree

7 files changed

+11
-9
lines changed

7 files changed

+11
-9
lines changed

cmd/dependabot/internal/cmd/test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ var testCmd = NewTestCommand()
8585
func readSmokeTest(file string) (*model.SmokeTest, []byte, error) {
8686
var smokeTest model.SmokeTest
8787

88-
data, err := os.ReadFile(file)
88+
data, err := os.ReadFile(file) //nolint:gosec // file path is provided by the user via CLI flags
8989
if err != nil {
9090
return nil, nil, fmt.Errorf("failed to open smoke test: %w", err)
9191
}

cmd/dependabot/internal/cmd/update.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ func readArguments(cmd *cobra.Command, flags *UpdateFlags) (*model.Input, error)
285285
func readInputFile(file string) (*model.Input, error) {
286286
var input model.Input
287287

288-
data, err := os.ReadFile(file)
288+
data, err := os.ReadFile(file) //nolint:gosec // file path is provided by the user via CLI flags
289289
if err != nil {
290290
return nil, fmt.Errorf("failed to open input file: %w", err)
291291
}

internal/infra/proxy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func NewProxy(ctx context.Context, cli *client.Client, params *RunParams, nets *
6969
}
7070
hostCfg.ExtraHosts = append(hostCfg.ExtraHosts, params.ExtraHosts...)
7171
if params.CacheDir != "" {
72-
_ = os.MkdirAll(params.CacheDir, 0744)
72+
_ = os.MkdirAll(params.CacheDir, 0750)
7373
cacheDir, _ := filepath.Abs(params.CacheDir)
7474
hostCfg.Mounts = append(hostCfg.Mounts, mount.Mount{
7575
Type: mount.TypeBind,

internal/infra/run.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func Run(params RunParams) error {
130130
var err error
131131
// Open a file for writing but don't truncate it yet since an error will delete the test.
132132
// This is done before the test so if the dir isn't writable it doesn't waste time.
133-
outFile, err = os.OpenFile(params.Output, os.O_RDWR|os.O_CREATE, 0666)
133+
outFile, err = os.OpenFile(params.Output, os.O_RDWR|os.O_CREATE, 0600)
134134
if err != nil {
135135
return fmt.Errorf("failed to create output file: %w", err)
136136
}
@@ -499,7 +499,7 @@ func getFromContainer(ctx context.Context, cli *client.Client, containerID, srcP
499499
defer outFile.Close()
500500
tarReader := tar.NewReader(reader)
501501
tarReader.Next()
502-
_, err = io.Copy(outFile, tarReader)
502+
_, err = io.Copy(outFile, io.LimitReader(tarReader, 1<<30)) // 1 GiB limit to prevent decompression bombs
503503
if err != nil {
504504
log.Printf("Failed copy while getting from container %v: %v\n", srcPath, err)
505505
}

internal/infra/run_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
)
1818

1919
func Test_checkCredAccess(t *testing.T) {
20-
l, err := net.Listen("tcp", ":0")
20+
l, err := net.Listen("tcp", "127.0.0.1:0")
2121
if err != nil {
2222
t.Fatal("Failed to create listener: ", err.Error())
2323
}

internal/server/input.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import (
44
"context"
55
"encoding/json"
66
"errors"
7-
"github.com/dependabot/cli/internal/model"
87
"log"
98
"net"
109
"net/http"
10+
"time"
11+
12+
"github.com/dependabot/cli/internal/model"
1113
)
1214

1315
type credServer struct {
@@ -30,7 +32,7 @@ func (s *credServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
3032
// Input receives configuration via HTTP on the port and returns it decoded
3133
func Input(listener net.Listener) (*model.Input, error) {
3234
handler := &credServer{}
33-
srv := &http.Server{Handler: handler}
35+
srv := &http.Server{Handler: handler, ReadHeaderTimeout: 10 * time.Second}
3436
handler.server = srv
3537

3638
// printing so the user doesn't think the cli is hanging

internal/server/input_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func TestInput(t *testing.T) {
3636

3737
url := fmt.Sprintf("http://%s", l.Addr().String())
3838
data := `{"job":{"package-manager":"test"},"credentials":[{"credential":"value"}]}`
39-
resp, err := http.Post(url, "application/json", bytes.NewReader([]byte(data)))
39+
resp, err := http.Post(url, "application/json", bytes.NewReader([]byte(data))) //nolint:gosec // test code with controlled URL
4040
if err != nil {
4141
t.Fatal(err.Error())
4242
}

0 commit comments

Comments
 (0)