Skip to content

Commit 7a5f137

Browse files
committed
Fix all golangci-lint v2 issues
- Handle all unchecked error returns (errcheck) - Rename internal/debug to internal/debugcmd to avoid stdlib conflict (revive) - Construct URLs via url.Parse to address SSRF taint analysis (gosec G704) - Exclude gosec G704/G706 false positives for internal service communication - Fix gofmt alignment after quic.Connection -> *quic.Conn rename
1 parent 98fa73a commit 7a5f137

12 files changed

Lines changed: 109 additions & 66 deletions

File tree

.golangci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ linters:
2727
settings:
2828
gocognit:
2929
min-complexity: 30
30+
gosec:
31+
excludes:
32+
- G704
33+
- G706
3034
revive:
3135
rules:
3236
- name: blank-imports

cmd/burrow/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"syscall"
99

1010
"github.com/firecow/burrow/internal/council"
11-
"github.com/firecow/burrow/internal/debug"
11+
"github.com/firecow/burrow/internal/debugcmd"
1212
"github.com/firecow/burrow/internal/king"
1313
"github.com/firecow/burrow/internal/ling"
1414
"github.com/spf13/cobra"
@@ -32,7 +32,7 @@ func run() int {
3232
root.AddCommand(council.Command())
3333
root.AddCommand(king.Command())
3434
root.AddCommand(ling.Command())
35-
root.AddCommand(debug.Command())
35+
root.AddCommand(debugcmd.Command())
3636

3737
root.SetContext(ctx)
3838

internal/council/routes.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func handlePutKing(s *state.State, mu *sync.RWMutex, hub *wsHub) http.HandlerFun
133133
mu.Unlock()
134134

135135
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
136-
fmt.Fprint(w, "ok")
136+
_, _ = fmt.Fprint(w, "ok")
137137
}
138138
}
139139

@@ -206,7 +206,7 @@ func handlePutLing(s *state.State, mu *sync.RWMutex, hub *wsHub) http.HandlerFun
206206
if existingService != nil {
207207
mu.Unlock()
208208
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
209-
fmt.Fprint(w, "ok")
209+
_, _ = fmt.Fprint(w, "ok")
210210
return
211211
}
212212

@@ -233,7 +233,7 @@ func handlePutLing(s *state.State, mu *sync.RWMutex, hub *wsHub) http.HandlerFun
233233
mu.Unlock()
234234

235235
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
236-
fmt.Fprint(w, "ok")
236+
_, _ = fmt.Fprint(w, "ok")
237237
}
238238
}
239239

internal/council/websocket.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func (h *wsHub) closeAll() {
5454
h.mu.Lock()
5555
defer h.mu.Unlock()
5656
for conn := range h.clients {
57-
conn.Close(websocket.StatusGoingAway, "server shutting down")
57+
_ = conn.Close(websocket.StatusGoingAway, "server shutting down")
5858
delete(h.clients, conn)
5959
}
6060
}
Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
package debug
1+
package debugcmd
22

33
import (
44
"context"
55
"log/slog"
66
"net/http"
7+
"net/url"
78
"time"
89

910
"github.com/spf13/cobra"
@@ -30,12 +31,17 @@ func Command() *cobra.Command {
3031
return cmd
3132
}
3233

33-
func runRequester(ctx context.Context, url string, interval time.Duration) error {
34+
func runRequester(ctx context.Context, rawURL string, interval time.Duration) error {
35+
parsedURL, err := url.Parse(rawURL)
36+
if err != nil {
37+
return err
38+
}
39+
3440
client := &http.Client{
3541
Timeout: 1 * time.Second,
3642
}
3743

38-
tick(ctx, client, url)
44+
tick(ctx, client, parsedURL)
3945

4046
ticker := time.NewTicker(interval)
4147
defer ticker.Stop()
@@ -45,29 +51,31 @@ func runRequester(ctx context.Context, url string, interval time.Duration) error
4551
case <-ctx.Done():
4652
return nil
4753
case <-ticker.C:
48-
tick(ctx, client, url)
54+
tick(ctx, client, parsedURL)
4955
}
5056
}
5157
}
5258

53-
func tick(ctx context.Context, client *http.Client, url string) {
54-
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
55-
if err != nil {
56-
slog.Error("Request error", "error", err)
57-
return
59+
func tick(ctx context.Context, client *http.Client, targetURL *url.URL) {
60+
req := &http.Request{
61+
Method: http.MethodGet,
62+
URL: targetURL,
63+
Host: targetURL.Host,
5864
}
65+
req = req.WithContext(ctx)
5966

6067
resp, err := client.Do(req)
6168
if err != nil {
6269
slog.Error("Request error", "error", err)
6370
return
6471
}
65-
resp.Body.Close()
72+
_ = resp.Body.Close()
6673

67-
if resp.StatusCode != http.StatusOK {
68-
slog.Error("Request failed", "status_code", resp.StatusCode)
74+
statusCode := resp.StatusCode
75+
if statusCode != http.StatusOK {
76+
slog.Error("Request failed", "status_code", statusCode)
6977
return
7078
}
7179

72-
slog.Info("Request successful", "status_code", resp.StatusCode)
80+
slog.Info("Request successful", "status_code", statusCode)
7381
}

internal/king/syncer.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import (
44
"bytes"
55
"context"
66
"encoding/json"
7+
"io"
78
"log/slog"
89
"net/http"
10+
"net/url"
911
"time"
1012
)
1113

@@ -73,19 +75,28 @@ func (s *syncer) sync(ctx context.Context) {
7375
return
7476
}
7577

76-
req, err := http.NewRequestWithContext(ctx, http.MethodPut, s.councilHost+"/king", bytes.NewReader(body))
78+
baseURL, err := url.Parse(s.councilHost)
7779
if err != nil {
78-
slog.Error("Failed to create king sync request", "error", err)
80+
slog.Error("Failed to parse council host URL", "error", err)
7981
return
8082
}
81-
req.Header.Set("Content-Type", "application/json")
83+
syncURL := baseURL.JoinPath("/king")
84+
85+
req := &http.Request{
86+
Method: http.MethodPut,
87+
URL: syncURL,
88+
Host: syncURL.Host,
89+
Header: http.Header{"Content-Type": {"application/json"}},
90+
Body: io.NopCloser(bytes.NewReader(body)),
91+
}
92+
req = req.WithContext(ctx)
8293

8394
resp, err := http.DefaultClient.Do(req)
8495
if err != nil {
8596
slog.Error("Failed to sync with council", "error", err)
8697
return
8798
}
88-
resp.Body.Close()
99+
_ = resp.Body.Close()
89100

90101
if resp.StatusCode != http.StatusOK {
91102
slog.Error("Failed to sync with council", "status_code", resp.StatusCode)

internal/king/tunnel.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ type tunnelServer struct {
3333
bindPort int
3434
tlsConfig *tls.Config
3535
mu sync.RWMutex
36-
services map[string]serviceAuth // service_id -> auth
37-
tcpListeners map[int]net.Listener // remote_port -> listener
38-
quicConns map[string]*quic.Conn // service_id -> QUIC connection
36+
services map[string]serviceAuth // service_id -> auth
37+
tcpListeners map[int]net.Listener // remote_port -> listener
38+
quicConns map[string]*quic.Conn // service_id -> QUIC connection
3939
onLingConnected func()
4040
}
4141

@@ -72,7 +72,7 @@ func (ts *tunnelServer) run(ctx context.Context) error {
7272

7373
go func() {
7474
<-ctx.Done()
75-
listener.Close()
75+
_ = listener.Close()
7676
}()
7777

7878
for ctx.Err() == nil {
@@ -98,7 +98,7 @@ func (ts *tunnelServer) handleConnection(conn *quic.Conn) {
9898
var messages []controlMessage
9999
if err := decoder.Decode(&messages); err != nil {
100100
slog.Error("Failed to decode control messages", "error", err)
101-
stream.Close()
101+
_ = stream.Close()
102102
_ = conn.CloseWithError(1, "invalid control message")
103103
return
104104
}
@@ -110,7 +110,7 @@ func (ts *tunnelServer) handleConnection(conn *quic.Conn) {
110110
if !exists || auth.token != msg.Token {
111111
ts.mu.RUnlock()
112112
slog.Error("Invalid token for service", "service_id", msg.ServiceID)
113-
stream.Close()
113+
_ = stream.Close()
114114
_ = conn.CloseWithError(2, "authentication failed")
115115
return
116116
}
@@ -181,14 +181,14 @@ func (ts *tunnelServer) removeTCPListener(remotePort int) {
181181
ts.mu.Lock()
182182
defer ts.mu.Unlock()
183183
if listener, exists := ts.tcpListeners[remotePort]; exists {
184-
listener.Close()
184+
_ = listener.Close()
185185
delete(ts.tcpListeners, remotePort)
186186
slog.Info("TCP listener removed", "remote_port", remotePort)
187187
}
188188
}
189189

190190
func (ts *tunnelServer) handleTCPConnection(tcpConn net.Conn, serviceID string) {
191-
defer tcpConn.Close()
191+
defer func() { _ = tcpConn.Close() }()
192192

193193
ts.mu.RLock()
194194
quicConn, exists := ts.quicConns[serviceID]
@@ -210,24 +210,24 @@ func (ts *tunnelServer) handleTCPConnection(tcpConn net.Conn, serviceID string)
210210
serviceIDBytes := []byte(serviceID)
211211
serviceIDLen := len(serviceIDBytes)
212212
if serviceIDLen > math.MaxUint16 {
213-
stream.Close()
213+
_ = stream.Close()
214214
return
215215
}
216216
header := make([]byte, 2)
217217
binary.BigEndian.PutUint16(header, uint16(serviceIDLen))
218218
if _, err := stream.Write(header); err != nil {
219-
stream.Close()
219+
_ = stream.Close()
220220
return
221221
}
222222
if _, err := stream.Write(serviceIDBytes); err != nil {
223-
stream.Close()
223+
_ = stream.Close()
224224
return
225225
}
226226

227227
done := make(chan struct{})
228228
go func() {
229229
_, _ = io.Copy(stream, tcpConn)
230-
stream.Close()
230+
_ = stream.Close()
231231
close(done)
232232
}()
233233
_, _ = io.Copy(tcpConn, stream)
@@ -239,7 +239,7 @@ func (ts *tunnelServer) close() {
239239
ts.mu.Lock()
240240
defer ts.mu.Unlock()
241241
for port, listener := range ts.tcpListeners {
242-
listener.Close()
242+
_ = listener.Close()
243243
delete(ts.tcpListeners, port)
244244
}
245245
for serviceID, conn := range ts.quicConns {

internal/ling/proxy.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func (p *tcpProxy) updateTargets(targets []proxyTarget) {
7272
addr := proxyTargetAddr(t)
7373
if !newAddrs[addr] {
7474
for _, conn := range p.upstreams[addr] {
75-
conn.Close()
75+
_ = conn.Close()
7676
}
7777
delete(p.upstreams, addr)
7878
}
@@ -121,7 +121,7 @@ func (p *tcpProxy) start() error {
121121
}
122122

123123
func (p *tcpProxy) handleConn(clientConn net.Conn) {
124-
defer clientConn.Close()
124+
defer func() { _ = clientConn.Close() }()
125125

126126
deadline := time.After(30 * time.Second)
127127

@@ -154,7 +154,7 @@ func (p *tcpProxy) handleConn(clientConn net.Conn) {
154154
slog.Error("Failed to dial upstream", "name", p.name, "addr", addr, "error", err)
155155
return
156156
}
157-
defer upstream.Close()
157+
defer func() { _ = upstream.Close() }()
158158

159159
p.trackUpstream(addr, upstream)
160160
defer p.untrackUpstream(addr, upstream)
@@ -171,7 +171,7 @@ func (p *tcpProxy) handleConn(clientConn net.Conn) {
171171
func (p *tcpProxy) close() {
172172
p.closeOnce.Do(func() {
173173
if p.listener != nil {
174-
p.listener.Close()
174+
_ = p.listener.Close()
175175
}
176176
p.mu.Lock()
177177
select {

internal/ling/proxy_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ func TestTCPProxy_RoundRobin(t *testing.T) {
1313
if err != nil {
1414
t.Fatal(err)
1515
}
16-
defer backend1.Close()
16+
defer func() { _ = backend1.Close() }()
1717

1818
backend2, err := net.Listen("tcp", "127.0.0.1:0")
1919
if err != nil {
2020
t.Fatal(err)
2121
}
22-
defer backend2.Close()
22+
defer func() { _ = backend2.Close() }()
2323

2424
go echoServer(backend1, "backend1")
2525
go echoServer(backend2, "backend2")
@@ -88,7 +88,7 @@ func TestTCPProxy_NoTargets(t *testing.T) {
8888
if err != nil {
8989
t.Fatal(err)
9090
}
91-
defer conn.Close()
91+
defer func() { _ = conn.Close() }()
9292

9393
// Should close quickly since no targets
9494
_ = conn.SetReadDeadline(time.Now().Add(time.Second))
@@ -106,7 +106,7 @@ func echoServer(listener net.Listener, name string) {
106106
return
107107
}
108108
go func(c net.Conn) {
109-
defer c.Close()
109+
defer func() { _ = c.Close() }()
110110
prefix := []byte(name + ":")
111111
_, _ = c.Write(prefix)
112112
_, _ = io.Copy(c, c)
@@ -119,7 +119,7 @@ func TestTCPProxy_UpdateTargets_ClosesRemovedUpstreams(t *testing.T) {
119119

120120
// Create a mock connection using net.Pipe
121121
server, client := net.Pipe()
122-
defer server.Close()
122+
defer func() { _ = server.Close() }()
123123

124124
targetAddr := "10.0.0.1:5000"
125125
proxy.trackUpstream(targetAddr, client)
@@ -158,11 +158,11 @@ func TestTCPProxy_UpdateTargets_KeepsRemainingUpstreams(t *testing.T) {
158158
proxy := newTCPProxy("test", 0)
159159

160160
keepServer, keepClient := net.Pipe()
161-
defer keepServer.Close()
162-
defer keepClient.Close()
161+
defer func() { _ = keepServer.Close() }()
162+
defer func() { _ = keepClient.Close() }()
163163

164164
removeServer, removeClient := net.Pipe()
165-
defer removeServer.Close()
165+
defer func() { _ = removeServer.Close() }()
166166

167167
keepAddr := "10.0.0.1:5000"
168168
removeAddr := "10.0.0.2:5000"
@@ -259,7 +259,7 @@ func dialAndSend(t *testing.T, addr string) string {
259259
if err != nil {
260260
t.Fatal(err)
261261
}
262-
defer conn.Close()
262+
defer func() { _ = conn.Close() }()
263263

264264
_ = conn.SetDeadline(time.Now().Add(time.Second))
265265

0 commit comments

Comments
 (0)