From 3ae441e862cd65e1b9d1ad8830aa7d062619c491 Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Wed, 5 Aug 2026 14:26:21 +0000 Subject: [PATCH] chore(lint): bump linter from v2.4.0 to v2.11.4 --- .golangci.yml | 1 + Dockerfile | 2 +- internal/configuration/settings/server.go | 2 +- internal/healthcheck/run.go | 2 +- internal/httpproxy/http.go | 2 +- internal/httpproxy/server.go | 2 +- internal/httpserver/run.go | 2 +- internal/mod/load_linux.go | 2 +- internal/openvpn/pkcs8/descbc.go | 2 +- internal/openvpn/start.go | 3 ++- internal/pmtud/icmp/df_linux.go | 5 +++-- internal/pmtud/ip/ipheader.go | 2 +- internal/pmtud/tcp/tcpheader.go | 2 +- internal/pprof/server_test.go | 2 +- internal/provider/protonvpn/updater/api.go | 4 ++-- internal/restrictednet/https.go | 2 +- internal/restrictednet/linux.go | 2 +- internal/server/openvpn.go | 2 +- internal/server/vpn.go | 2 +- internal/socks5/response.go | 2 +- internal/socks5/server.go | 2 +- internal/socks5/socks5_test.go | 9 +++++---- internal/vpn/run.go | 2 +- internal/wireguard/offload_linux.go | 6 ++++-- 24 files changed, 35 insertions(+), 29 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 5f274fad..326eaf76 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -46,6 +46,7 @@ linters: - dupl - err113 - maintidx + - prealloc path: _test\.go - linters: - dupl diff --git a/Dockerfile b/Dockerfile index 9b4578e2..29fc0c55 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ ARG ALPINE_VERSION=3.23 ARG GO_ALPINE_VERSION=3.23 ARG GO_VERSION=1.25 ARG XCPUTRANSLATE_VERSION=v0.9.0 -ARG GOLANGCI_LINT_VERSION=v2.4.0 +ARG GOLANGCI_LINT_VERSION=v2.11.4 ARG MOCKGEN_VERSION=v0.6.0 ARG BUILDPLATFORM=linux/amd64 diff --git a/internal/configuration/settings/server.go b/internal/configuration/settings/server.go index dfee5672..16e4f9c1 100644 --- a/internal/configuration/settings/server.go +++ b/internal/configuration/settings/server.go @@ -95,7 +95,7 @@ func (c *ControlServer) setDefaults() { var role auth.Role _ = json.Unmarshal([]byte(c.AuthDefaultRole), &role) role.Name = "default" - roleBytes, _ := json.Marshal(role) //nolint:errchkjson + roleBytes, _ := json.Marshal(role) //nolint:errchkjson,gosec c.AuthDefaultRole = string(roleBytes) } } diff --git a/internal/healthcheck/run.go b/internal/healthcheck/run.go index 55980381..8708ffb5 100644 --- a/internal/healthcheck/run.go +++ b/internal/healthcheck/run.go @@ -19,7 +19,7 @@ func (s *Server) Run(ctx context.Context, done chan<- struct{}) { ReadTimeout: readTimeout, } serverDone := make(chan struct{}) - go func() { + go func() { //nolint:gosec defer close(serverDone) <-ctx.Done() const shutdownGraceDuration = 2 * time.Second diff --git a/internal/httpproxy/http.go b/internal/httpproxy/http.go index 28583ec1..4edd54c0 100644 --- a/internal/httpproxy/http.go +++ b/internal/httpproxy/http.go @@ -29,7 +29,7 @@ func (h *handler) handleHTTP(responseWriter http.ResponseWriter, request *http.R setForwardedHeaders(request) } - response, err := h.client.Do(request) + response, err := h.client.Do(request) //nolint:gosec // SSRF is the feature: HTTP proxy forwards to arbitrary URLs if err != nil { http.Error(responseWriter, "server error", http.StatusInternalServerError) h.logger.Warn("cannot process request for client " + request.RemoteAddr + ": " + err.Error()) diff --git a/internal/httpproxy/server.go b/internal/httpproxy/server.go index 9c301eec..f7f1c608 100644 --- a/internal/httpproxy/server.go +++ b/internal/httpproxy/server.go @@ -38,7 +38,7 @@ func (s *Server) Run(ctx context.Context, errorCh chan<- error) { ReadHeaderTimeout: s.readHeaderTimeout, ReadTimeout: s.readTimeout, } - go func() { + go func() { //nolint:gosec <-ctx.Done() const shutdownGraceDuration = 100 * time.Millisecond shutdownCtx, cancel := context.WithTimeout(context.Background(), shutdownGraceDuration) diff --git a/internal/httpserver/run.go b/internal/httpserver/run.go index 3a187b62..41768c4d 100644 --- a/internal/httpserver/run.go +++ b/internal/httpserver/run.go @@ -21,7 +21,7 @@ func (s *Server) Run(ctx context.Context, ready chan<- struct{}, done chan<- str crashed := make(chan struct{}) shutdownDone := make(chan struct{}) listenCtx, listenCancel := context.WithCancel(ctx) - go func() { + go func() { //nolint:gosec defer close(shutdownDone) defer listenCancel() select { diff --git a/internal/mod/load_linux.go b/internal/mod/load_linux.go index 236d105a..45b3eb5c 100644 --- a/internal/mod/load_linux.go +++ b/internal/mod/load_linux.go @@ -67,7 +67,7 @@ func initModule(path string) (err error) { default: const moduleParams = "" const flags = 0 - err = unix.FinitModule(int(file.Fd()), moduleParams, flags) + err = unix.FinitModule(int(file.Fd()), moduleParams, flags) //nolint:gosec switch { case err == nil, err == unix.EEXIST: //nolint:err113 return nil diff --git a/internal/openvpn/pkcs8/descbc.go b/internal/openvpn/pkcs8/descbc.go index 3c9d0cc6..de66722a 100644 --- a/internal/openvpn/pkcs8/descbc.go +++ b/internal/openvpn/pkcs8/descbc.go @@ -42,7 +42,7 @@ func (c cipherDESCBC) Encrypt(key, iv, plaintext []byte) ([]byte, error) { ciphertext := make([]byte, len(plaintext)+paddingLen) copy(ciphertext, plaintext) copy(ciphertext[len(plaintext):], - bytes.Repeat([]byte{byte(paddingLen)}, paddingLen)) + bytes.Repeat([]byte{byte(paddingLen)}, paddingLen)) //nolint:gosec blockEncrypter.CryptBlocks(ciphertext, ciphertext) return ciphertext, nil } diff --git a/internal/openvpn/start.go b/internal/openvpn/start.go index f78082a7..3ace9bb7 100644 --- a/internal/openvpn/start.go +++ b/internal/openvpn/start.go @@ -26,7 +26,8 @@ func start(ctx context.Context, starter CmdStarter, version string, flags []stri return nil, nil, nil, fmt.Errorf("OpenVPN version is unknown: %s", version) } - args := []string{"--config", configPath} + args := make([]string, 0, 2+len(flags)) //nolint:mnd + args = append(args, "--config", configPath) args = append(args, flags...) cmd := exec.CommandContext(ctx, bin, args...) setCmdSysProcAttr(cmd) diff --git a/internal/pmtud/icmp/df_linux.go b/internal/pmtud/icmp/df_linux.go index a0fd6f9c..2ca0e25e 100644 --- a/internal/pmtud/icmp/df_linux.go +++ b/internal/pmtud/icmp/df_linux.go @@ -5,10 +5,11 @@ import ( ) func setDontFragment(fd uintptr, ipv4 bool) (err error) { + fdInt := int(fd) //nolint:gosec if ipv4 { - return unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, + return unix.SetsockoptInt(fdInt, unix.IPPROTO_IP, unix.IP_MTU_DISCOVER, unix.IP_PMTUDISC_PROBE) } - return unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, + return unix.SetsockoptInt(fdInt, unix.IPPROTO_IPV6, unix.IPV6_MTU_DISCOVER, unix.IPV6_PMTUDISC_PROBE) } diff --git a/internal/pmtud/ip/ipheader.go b/internal/pmtud/ip/ipheader.go index b0139b9b..384af0d1 100644 --- a/internal/pmtud/ip/ipheader.go +++ b/internal/pmtud/ip/ipheader.go @@ -52,7 +52,7 @@ func ipChecksum(header []byte) uint16 { for (sum >> 16) > 0 { sum = (sum & 0xFFFF) + (sum >> 16) } - return ^uint16(sum) //nolint:gosec + return ^uint16(sum) } // HeaderV6 makes an IPv6 header. diff --git a/internal/pmtud/tcp/tcpheader.go b/internal/pmtud/tcp/tcpheader.go index aa1ab70f..1e7bd1cc 100644 --- a/internal/pmtud/tcp/tcpheader.go +++ b/internal/pmtud/tcp/tcpheader.go @@ -58,7 +58,7 @@ func tcpChecksum(ipHeader, tcpHeader, payload []byte) uint16 { for (sum >> 16) > 0 { sum = (sum & 0xFFFF) + (sum >> 16) } - return ^uint16(sum) //nolint:gosec + return ^uint16(sum) } const ( diff --git a/internal/pprof/server_test.go b/internal/pprof/server_test.go index 35d60775..9601e32e 100644 --- a/internal/pprof/server_test.go +++ b/internal/pprof/server_test.go @@ -82,7 +82,7 @@ func Test_Server(t *testing.T) { require.NoError(t, err) go func(client *http.Client, request *http.Request, results chan<- httpResult) { - response, err := client.Do(request) //nolint:bodyclose + response, err := client.Do(request) //nolint:bodyclose,gosec // test code accessing local pprof server results <- httpResult{ url: request.URL.String(), response: response, diff --git a/internal/provider/protonvpn/updater/api.go b/internal/provider/protonvpn/updater/api.go index dab78eb4..422d73a8 100644 --- a/internal/provider/protonvpn/updater/api.go +++ b/internal/provider/protonvpn/updater/api.go @@ -232,7 +232,7 @@ func (c *apiClient) cookieToken(ctx context.Context, sessionID, tokenType, acces buffer := bytes.NewBuffer(nil) encoder := json.NewEncoder(buffer) - if err := encoder.Encode(requestBody); err != nil { + if err := encoder.Encode(requestBody); err != nil { //nolint:gosec return "", fmt.Errorf("encoding request body: %w", err) } @@ -536,7 +536,7 @@ func httpHeadersToString(headers http.Header) string { if !first { builder.WriteString(", ") } - builder.WriteString(fmt.Sprintf("%s: %s", key, value)) + fmt.Fprintf(&builder, "%s: %s", key, value) first = false } } diff --git a/internal/restrictednet/https.go b/internal/restrictednet/https.go index 4d1f15c1..d681584c 100644 --- a/internal/restrictednet/https.go +++ b/internal/restrictednet/https.go @@ -150,7 +150,7 @@ func connectSourceConnection(ctx context.Context, fd int, destinationAddrPort ne return nil, fmt.Errorf("connecting socket: %w", err) } - file := os.NewFile(uintptr(fd), "") + file := os.NewFile(uintptr(fd), "") //nolint:gosec if file == nil { closeFD(fd) return nil, fmt.Errorf("creating socket file for destination %s", destinationAddrPort) diff --git a/internal/restrictednet/linux.go b/internal/restrictednet/linux.go index c32126b4..358fb828 100644 --- a/internal/restrictednet/linux.go +++ b/internal/restrictednet/linux.go @@ -75,7 +75,7 @@ func connectFD(ctx context.Context, fd int, destination netip.AddrPort) error { if err != nil { return fmt.Errorf("getsockopt error: %w", err) } else if n != 0 { - return fmt.Errorf("connect failed asynchronously: %w", unix.Errno(n)) + return fmt.Errorf("connect failed asynchronously: %w", unix.Errno(n)) //nolint:gosec } return nil diff --git a/internal/server/openvpn.go b/internal/server/openvpn.go index 66a9a620..dcb16f36 100644 --- a/internal/server/openvpn.go +++ b/internal/server/openvpn.go @@ -112,7 +112,7 @@ func (h *openvpnHandler) getSettings(w http.ResponseWriter) { vpnSettings := h.looper.GetSettings() settings := vpnSettings.OpenVPN encoder := json.NewEncoder(w) - if err := encoder.Encode(settings); err != nil { + if err := encoder.Encode(settings); err != nil { //nolint:gosec h.warner.Warn(err.Error()) w.WriteHeader(http.StatusInternalServerError) return diff --git a/internal/server/vpn.go b/internal/server/vpn.go index 84f21c83..0ce3cb04 100644 --- a/internal/server/vpn.go +++ b/internal/server/vpn.go @@ -124,7 +124,7 @@ func (h *vpnHandler) patchSettings(w http.ResponseWriter, r *http.Request) { } outcome := h.looper.SetSettings(h.ctx, updatedSettings) - _, err = w.Write([]byte(outcome)) + _, err = w.Write([]byte(outcome)) //nolint:gosec // internal API writes status outcome, not HTML rendered in browser if err != nil { h.warner.Warn("writing response: " + err.Error()) } diff --git a/internal/socks5/response.go b/internal/socks5/response.go index ffa27f7c..9d0b31a4 100644 --- a/internal/socks5/response.go +++ b/internal/socks5/response.go @@ -82,7 +82,7 @@ func encodeBindData(addrType addrType, address string, port uint16) ( if len(address) > maxDomainNameLength { return nil, fmt.Errorf("%w: %s", ErrDomainNameTooLong, address) } - data = append(data, byte(len(address))) + data = append(data, byte(len(address))) //nolint:gosec data = append(data, []byte(address)...) default: panic(fmt.Sprintf("unsupported address type %d", addrType)) diff --git a/internal/socks5/server.go b/internal/socks5/server.go index 9a5e2202..c566d841 100644 --- a/internal/socks5/server.go +++ b/internal/socks5/server.go @@ -39,7 +39,7 @@ func (s *server) String() string { } func (s *server) Start(ctx context.Context) (runErr <-chan error, err error) { - s.socksConnCtx, s.socksConnCancel = context.WithCancel(context.Background()) + s.socksConnCtx, s.socksConnCancel = context.WithCancel(context.Background()) //nolint:gosec config := &net.ListenConfig{} s.tcpListener, err = config.Listen(ctx, "tcp", s.address) if err != nil { diff --git a/internal/socks5/socks5_test.go b/internal/socks5/socks5_test.go index 982dace3..58ef128d 100644 --- a/internal/socks5/socks5_test.go +++ b/internal/socks5/socks5_test.go @@ -292,7 +292,7 @@ func dialSOCKS5(t *testing.T, proxyAddr, targetAddr, username, password string) connectRequest = []byte{socks5Version, byte(connect), 0, byte(ipv4)} connectRequest = append(connectRequest, ip...) } else { - connectRequest = []byte{socks5Version, byte(connect), 0, byte(domainName), byte(len(host))} + connectRequest = []byte{socks5Version, byte(connect), 0, byte(domainName), byte(len(host))} //nolint:gosec connectRequest = append(connectRequest, []byte(host)...) } connectRequest = binary.BigEndian.AppendUint16(connectRequest, uint16(targetPort)) //nolint:gosec @@ -350,9 +350,10 @@ func negotiateSOCKS5(t *testing.T, conn net.Conn, username, password string) { require.Equal(t, byte(method), methodResp[1]) if method == authUsernamePassword { - packet := []byte{authUsernamePasswordSubNegotiation1, byte(len(username))} + packet := make([]byte, 0, 2+len(username)+len(password)) + packet = append(packet, authUsernamePasswordSubNegotiation1, byte(len(username))) //nolint:gosec packet = append(packet, []byte(username)...) - packet = append(packet, byte(len(password))) + packet = append(packet, byte(len(password))) //nolint:gosec packet = append(packet, []byte(password)...) _, err = conn.Write(packet) require.NoError(t, err) @@ -443,7 +444,7 @@ func makeSOCKS5UDPDatagram(targetAddress string, payload []byte) ([]byte, error) if len(host) > 255 { return nil, errors.New("domain name too long") } - datagram = append(datagram, byte(domainName), byte(len(host))) + datagram = append(datagram, byte(domainName), byte(len(host))) //nolint:gosec datagram = append(datagram, []byte(host)...) } datagram = binary.BigEndian.AppendUint16(datagram, uint16(port)) diff --git a/internal/vpn/run.go b/internal/vpn/run.go index 1e49bbe4..793ae612 100644 --- a/internal/vpn/run.go +++ b/internal/vpn/run.go @@ -91,7 +91,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) { for stayHere { select { case <-tunnelReady: - go l.onTunnelUp(vpnCtx, ctx, tunnelUpData) + go l.onTunnelUp(vpnCtx, ctx, tunnelUpData) //nolint:gosec case <-ctx.Done(): l.cleanup() vpnCancel() diff --git a/internal/wireguard/offload_linux.go b/internal/wireguard/offload_linux.go index 3140193f..ed7329e7 100644 --- a/internal/wireguard/offload_linux.go +++ b/internal/wireguard/offload_linux.go @@ -12,7 +12,9 @@ import ( // omitted so wireguard-go's initFromFlags sees no vnet header support and // keeps tun.vnetHdr=false, falling back to simple single-packet writes instead // of the GRO/GSO batch path that causes EINVAL on some vendor kernels. -func createTUN(name string, mtu int, gso bool) (tun.Device, error) { //nolint:ireturn +// +//nolint:ireturn +func createTUN(name string, mtu int, gso bool) (tun.Device, error) { if gso { return tun.CreateTUN(name, mtu) } @@ -49,5 +51,5 @@ func OpenTUNFile(name string) (*os.File, error) { unix.Close(tunFD) return nil, fmt.Errorf("setting nonblock: %w", err) } - return os.NewFile(uintptr(tunFD), "/dev/net/tun"), nil + return os.NewFile(uintptr(tunFD), "/dev/net/tun"), nil //nolint:gosec }