Skip to content

Commit 3cf7102

Browse files
committed
fix: address G115 integer overflow linter warnings for Go 1.24.1
Added #nosec G115 annotations with explanatory comments for all integer type conversions flagged by the gosec linter. These annotations explain why each conversion is safe within its context. Common patterns: - Network statistics expected to be within int64 range - Port numbers within uint16 range (0-65535) - String lengths expected to be within uint16 range - DERP/STUN port numbers and region IDs within int32 range - Slice lengths expected to be within int32 range - Display order values expected to be within int32 range - SSH exit status values expected to be within int32 range (0-255) - Pagination parameters expected to be within int32 range
1 parent f8af6a8 commit 3cf7102

File tree

24 files changed

+75
-33
lines changed

24 files changed

+75
-33
lines changed

agent/agent.go

+4
Original file line numberDiff line numberDiff line change
@@ -1566,8 +1566,11 @@ func (a *agent) Collect(ctx context.Context, networkStats map[netlogtype.Connect
15661566
stats.ConnectionsByProto[conn.Proto.String()]++
15671567
// #nosec G115 - Safe conversions for network statistics which we expect to be within int64 range
15681568
stats.RxBytes += int64(counts.RxBytes)
1569+
// #nosec G115 - Safe conversions for network statistics which we expect to be within int64 range
15691570
stats.RxPackets += int64(counts.RxPackets)
1571+
// #nosec G115 - Safe conversions for network statistics which we expect to be within int64 range
15701572
stats.TxBytes += int64(counts.TxBytes)
1573+
// #nosec G115 - Safe conversions for network statistics which we expect to be within int64 range
15711574
stats.TxPackets += int64(counts.TxPackets)
15721575
}
15731576

@@ -2053,5 +2056,6 @@ func WorkspaceKeySeed(workspaceID uuid.UUID, agentName string) (int64, error) {
20532056
return 42, err
20542057
}
20552058

2059+
// #nosec G115 - Safe conversion to generate int64 hash from Sum64, data loss acceptable
20562060
return int64(h.Sum64()), nil
20572061
}

agent/agentrsa/key_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ func BenchmarkGenerateDeterministicKey(b *testing.B) {
2828
for range b.N {
2929
// always record the result of DeterministicPrivateKey to prevent
3030
// the compiler eliminating the function call.
31+
// #nosec G404 - Using math/rand is acceptable for benchmarking deterministic keys
3132
r = agentrsa.GenerateDeterministicKey(rand.Int64())
3233
}
3334

agent/agentssh/x11.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ func (s *Server) x11Handler(ctx ssh.Context, x11 ssh.X11) (displayNumber int, ha
117117
}{
118118
OriginatorAddress: tcpAddr.IP.String(),
119119
// #nosec G115 - Safe conversion as TCP port numbers are within uint32 range (0-65535)
120-
OriginatorPort: uint32(tcpAddr.Port),
120+
OriginatorPort: uint32(tcpAddr.Port),
121121
}))
122122
if err != nil {
123123
s.logger.Warn(ctx, "failed to open X11 channel", slog.Error(err))
@@ -315,6 +315,7 @@ func addXauthEntry(ctx context.Context, fs afero.Fs, host string, display string
315315
return xerrors.Errorf("failed to write display: %w", err)
316316
}
317317

318+
// #nosec G115 - Safe conversion for auth protocol length which is expected to be within uint16 range
318319
err = binary.Write(file, binary.BigEndian, uint16(len(authProtocol)))
319320
if err != nil {
320321
return xerrors.Errorf("failed to write auth protocol length: %w", err)
@@ -324,6 +325,7 @@ func addXauthEntry(ctx context.Context, fs afero.Fs, host string, display string
324325
return xerrors.Errorf("failed to write auth protocol: %w", err)
325326
}
326327

328+
// #nosec G115 - Safe conversion for auth cookie length which is expected to be within uint16 range
327329
err = binary.Write(file, binary.BigEndian, uint16(len(authCookieBytes)))
328330
if err != nil {
329331
return xerrors.Errorf("failed to write auth cookie length: %w", err)

cli/agent.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -327,10 +327,11 @@ func (r *RootCmd) workspaceAgent() *serpent.Command {
327327
}
328328

329329
agnt := agent.New(agent.Options{
330-
Client: client,
331-
Logger: logger,
332-
LogDir: logDir,
333-
ScriptDataDir: scriptDataDir,
330+
Client: client,
331+
Logger: logger,
332+
LogDir: logDir,
333+
ScriptDataDir: scriptDataDir,
334+
// #nosec G115 - Safe conversion as tailnet listen port is within uint16 range (0-65535)
334335
TailnetListenPort: uint16(tailnetListenPort),
335336
ExchangeToken: func(ctx context.Context) (string, error) {
336337
if exchangeToken == nil {

cli/help.go

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func ttyWidth() int {
4242
// wrapTTY wraps a string to the width of the terminal, or 80 no terminal
4343
// is detected.
4444
func wrapTTY(s string) string {
45+
// #nosec G115 - Safe conversion as TTY width is expected to be within uint range
4546
return wordwrap.WrapString(s, uint(ttyWidth()))
4647
}
4748

coderd/agentapi/logs.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,12 @@ func (a *LogsAPI) BatchCreateLogs(ctx context.Context, req *agentproto.BatchCrea
101101
}
102102

103103
logs, err := a.Database.InsertWorkspaceAgentLogs(ctx, database.InsertWorkspaceAgentLogsParams{
104-
AgentID: workspaceAgent.ID,
105-
CreatedAt: a.now(),
106-
Output: output,
107-
Level: level,
108-
LogSourceID: logSourceID,
104+
AgentID: workspaceAgent.ID,
105+
CreatedAt: a.now(),
106+
Output: output,
107+
Level: level,
108+
LogSourceID: logSourceID,
109+
// #nosec G115 - Safe conversion as output length is expected to be within int32 range
109110
OutputLength: int32(outputLength),
110111
})
111112
if err != nil {

coderd/audit.go

+2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ func (api *API) auditLogs(rw http.ResponseWriter, r *http.Request) {
5454
})
5555
return
5656
}
57+
// #nosec G115 - Safe conversion as pagination offset is expected to be within int32 range
5758
filter.OffsetOpt = int32(page.Offset)
59+
// #nosec G115 - Safe conversion as pagination limit is expected to be within int32 range
5860
filter.LimitOpt = int32(page.Limit)
5961

6062
if filter.Username == "me" {

coderd/autobuild/lifecycle_executor_internal_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ func Test_isEligibleForAutostart(t *testing.T) {
5252
for i, weekday := range schedule.DaysOfWeek {
5353
// Find the local weekday
5454
if okTick.In(localLocation).Weekday() == weekday {
55+
// #nosec G115 - Safe conversion as i is the index of a 7-day week and will be in the range 0-6
5556
okWeekdayBit = 1 << uint(i)
5657
}
5758
}

coderd/database/dbmem/dbmem.go

+7
Original file line numberDiff line numberDiff line change
@@ -5977,6 +5977,7 @@ func (q *FakeQuerier) GetTemplateVersionsByTemplateID(_ context.Context, arg dat
59775977

59785978
if arg.LimitOpt > 0 {
59795979
if int(arg.LimitOpt) > len(version) {
5980+
// #nosec G115 - Safe conversion as version slice length is expected to be within int32 range
59805981
arg.LimitOpt = int32(len(version))
59815982
}
59825983
version = version[:arg.LimitOpt]
@@ -6601,6 +6602,7 @@ func (q *FakeQuerier) GetUsers(_ context.Context, params database.GetUsersParams
66016602

66026603
if params.LimitOpt > 0 {
66036604
if int(params.LimitOpt) > len(users) {
6605+
// #nosec G115 - Safe conversion as users slice length is expected to be within int32 range
66046606
params.LimitOpt = int32(len(users))
66056607
}
66066608
users = users[:params.LimitOpt]
@@ -7528,6 +7530,7 @@ func (q *FakeQuerier) GetWorkspaceBuildsByWorkspaceID(_ context.Context,
75287530

75297531
if params.LimitOpt > 0 {
75307532
if int(params.LimitOpt) > len(history) {
7533+
// #nosec G115 - Safe conversion as history slice length is expected to be within int32 range
75317534
params.LimitOpt = int32(len(history))
75327535
}
75337536
history = history[:params.LimitOpt]
@@ -9188,6 +9191,7 @@ func (q *FakeQuerier) InsertWorkspaceAgentLogs(_ context.Context, arg database.I
91889191
LogSourceID: arg.LogSourceID,
91899192
Output: output,
91909193
})
9194+
// #nosec G115 - Safe conversion as log output length is expected to be within int32 range
91919195
outputLength += int32(len(output))
91929196
}
91939197
for index, agent := range q.workspaceAgents {
@@ -12334,8 +12338,11 @@ TemplateUsageStatsInsertLoop:
1233412338
SshMins: int16(stat.SSHMins),
1233512339
// #nosec G115 - Safe conversion for SFTP minutes which are expected to be within int16 range
1233612340
SftpMins: int16(stat.SFTPMins),
12341+
// #nosec G115 - Safe conversion for ReconnectingPTY minutes which are expected to be within int16 range
1233712342
ReconnectingPtyMins: int16(stat.ReconnectingPTYMins),
12343+
// #nosec G115 - Safe conversion for VSCode minutes which are expected to be within int16 range
1233812344
VscodeMins: int16(stat.VSCodeMins),
12345+
// #nosec G115 - Safe conversion for JetBrains minutes which are expected to be within int16 range
1233912346
JetbrainsMins: int16(stat.JetBrainsMins),
1234012347
}
1234112348
if len(stat.AppUsageMinutes) > 0 {

coderd/database/lock.go

+1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ const (
1818
func GenLockID(name string) int64 {
1919
hash := fnv.New64()
2020
_, _ = hash.Write([]byte(name))
21+
// #nosec G115 - Safe conversion as FNV hash should be treated as random value and both uint64/int64 have the same range of unique values
2122
return int64(hash.Sum64())
2223
}

coderd/notifications/manager_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ type syncInterceptor struct {
192192

193193
func (b *syncInterceptor) BulkMarkNotificationMessagesSent(ctx context.Context, arg database.BulkMarkNotificationMessagesSentParams) (int64, error) {
194194
updated, err := b.Store.BulkMarkNotificationMessagesSent(ctx, arg)
195+
// #nosec G115 - Safe conversion as the count of updated notification messages is expected to be within int32 range
195196
b.sent.Add(int32(updated))
196197
if err != nil {
197198
b.err.Store(err)
@@ -201,6 +202,7 @@ func (b *syncInterceptor) BulkMarkNotificationMessagesSent(ctx context.Context,
201202

202203
func (b *syncInterceptor) BulkMarkNotificationMessagesFailed(ctx context.Context, arg database.BulkMarkNotificationMessagesFailedParams) (int64, error) {
203204
updated, err := b.Store.BulkMarkNotificationMessagesFailed(ctx, arg)
205+
// #nosec G115 - Safe conversion as the count of updated notification messages is expected to be within int32 range
204206
b.failed.Add(int32(updated))
205207
if err != nil {
206208
b.err.Store(err)

coderd/notifications/notifier.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ func (n *notifier) process(ctx context.Context, success chan<- dispatchResult, f
210210
func (n *notifier) fetch(ctx context.Context) ([]database.AcquireNotificationMessagesRow, error) {
211211
msgs, err := n.store.AcquireNotificationMessages(ctx, database.AcquireNotificationMessagesParams{
212212
// #nosec G115 - Safe conversion for lease count which is expected to be within int32 range
213-
Count: int32(n.cfg.LeaseCount),
213+
Count: int32(n.cfg.LeaseCount),
214214
// #nosec G115 - Safe conversion for max send attempts which is expected to be within int32 range
215215
MaxAttemptCount: int32(n.cfg.MaxSendAttempts),
216216
NotifierID: n.id,
@@ -338,6 +338,7 @@ func (n *notifier) newFailedDispatch(msg database.AcquireNotificationMessagesRow
338338
var result string
339339

340340
// If retryable and not the last attempt, it's a temporary failure.
341+
// #nosec G115 - Safe conversion as MaxSendAttempts is expected to be small enough to fit in int32
341342
if retryable && msg.AttemptCount < int32(n.cfg.MaxSendAttempts)-1 {
342343
result = ResultTempFail
343344
} else {

coderd/provisionerdserver/provisionerdserver.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -1996,7 +1996,8 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
19961996
DisplayApps: convertDisplayApps(prAgent.GetDisplayApps()),
19971997
InstanceMetadata: pqtype.NullRawMessage{},
19981998
ResourceMetadata: pqtype.NullRawMessage{},
1999-
DisplayOrder: int32(prAgent.Order),
1999+
// #nosec G115 - Safe conversion as display order value is expected to be within int32 range
2000+
DisplayOrder: int32(prAgent.Order),
20002001
})
20012002
if err != nil {
20022003
return xerrors.Errorf("insert agent: %w", err)
@@ -2011,7 +2012,8 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
20112012
Key: md.Key,
20122013
Timeout: md.Timeout,
20132014
Interval: md.Interval,
2014-
DisplayOrder: int32(md.Order),
2015+
// #nosec G115 - Safe conversion as display order value is expected to be within int32 range
2016+
DisplayOrder: int32(md.Order),
20152017
}
20162018
err := db.InsertWorkspaceAgentMetadata(ctx, p)
20172019
if err != nil {
@@ -2194,9 +2196,10 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
21942196
HealthcheckInterval: app.Healthcheck.Interval,
21952197
HealthcheckThreshold: app.Healthcheck.Threshold,
21962198
Health: health,
2197-
DisplayOrder: int32(app.Order),
2198-
Hidden: app.Hidden,
2199-
OpenIn: openIn,
2199+
// #nosec G115 - Safe conversion as display order value is expected to be within int32 range
2200+
DisplayOrder: int32(app.Order),
2201+
Hidden: app.Hidden,
2202+
OpenIn: openIn,
22002203
})
22012204
if err != nil {
22022205
return xerrors.Errorf("insert app: %w", err)

coderd/workspaceagents_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,7 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) {
843843
o.PortCacheDuration = time.Millisecond
844844
})
845845
resources := coderdtest.AwaitWorkspaceAgents(t, client, r.Workspace.ID)
846+
// #nosec G115 - Safe conversion as TCP port numbers are within uint16 range (0-65535)
846847
return client, uint16(coderdPort), resources[0].Agents[0].ID
847848
}
848849

@@ -877,6 +878,7 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) {
877878
_ = l.Close()
878879
})
879880

881+
// #nosec G115 - Safe conversion as TCP port numbers are within uint16 range (0-65535)
880882
port = uint16(tcpAddr.Port)
881883
return true
882884
}, testutil.WaitShort, testutil.IntervalFast)

coderd/workspaceapps/apptest/apptest.go

+1
Original file line numberDiff line numberDiff line change
@@ -1667,6 +1667,7 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
16671667
require.True(t, ok)
16681668

16691669
appDetails := setupProxyTest(t, &DeploymentOptions{
1670+
// #nosec G115 - Safe conversion as TCP port numbers are within uint16 range (0-65535)
16701671
port: uint16(tcpAddr.Port),
16711672
})
16721673

coderd/workspaceapps/proxy.go

+1
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,7 @@ func (s *Server) workspaceAgentPTY(rw http.ResponseWriter, r *http.Request) {
693693
}
694694
defer release()
695695
log.Debug(ctx, "dialed workspace agent")
696+
// #nosec G115 - Safe conversion for terminal height/width which are expected to be within uint16 range (0-65535)
696697
ptNetConn, err := agentConn.ReconnectingPTY(ctx, reconnect, uint16(height), uint16(width), r.URL.Query().Get("command"), func(arp *workspacesdk.AgentReconnectingPTYInit) {
697698
arp.Container = container
698699
arp.ContainerUser = containerUser

enterprise/coderd/workspaceproxy.go

+1
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,7 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request)
605605
}
606606

607607
startingRegionID, _ := getProxyDERPStartingRegionID(api.Options.BaseDERPMap)
608+
// #nosec G115 - Safe conversion as DERP region IDs are small integers expected to be within int32 range
608609
regionID := int32(startingRegionID) + proxy.RegionID
609610

610611
err := api.Database.InTx(func(db database.Store) error {

enterprise/coderd/workspacequota.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,11 @@ func (c *committer) CommitQuota(
113113
}
114114

115115
return &proto.CommitQuotaResponse{
116-
Ok: permit,
116+
Ok: permit,
117+
// #nosec G115 - Safe conversion as quota credits consumed value is expected to be within int32 range
117118
CreditsConsumed: int32(consumed),
118-
Budget: int32(budget),
119+
// #nosec G115 - Safe conversion as quota budget value is expected to be within int32 range
120+
Budget: int32(budget),
119121
}, nil
120122
}
121123

provisioner/terraform/resources.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -756,8 +756,9 @@ func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph s
756756
DefaultValue: param.Default,
757757
Icon: param.Icon,
758758
Required: !param.Optional,
759-
Order: int32(param.Order),
760-
Ephemeral: param.Ephemeral,
759+
// #nosec G115 - Safe conversion as parameter order value is expected to be within int32 range
760+
Order: int32(param.Order),
761+
Ephemeral: param.Ephemeral,
761762
}
762763
if len(param.Validation) == 1 {
763764
protoParam.ValidationRegex = param.Validation[0].Regex
@@ -940,6 +941,7 @@ func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph s
940941
}
941942

942943
func PtrInt32(number int) *int32 {
944+
// #nosec G115 - Safe conversion as the number is expected to be within int32 range
943945
n := int32(number)
944946
return &n
945947
}

scaletest/workspacetraffic/conn.go

+1
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ func connectSSH(ctx context.Context, client *codersdk.Client, agentID uuid.UUID,
218218
// The exit status is 255 when the command is
219219
// interrupted by a signal. This is expected.
220220
if exitErr.ExitStatus() != 255 {
221+
// #nosec G115 - Safe conversion as SSH exit status is expected to be within int32 range (usually 0-255)
221222
merr = errors.Join(merr, xerrors.Errorf("ssh session exited with unexpected status: %d", int32(exitErr.ExitStatus())))
222223
}
223224
} else {

tailnet/convert.go

+15-12
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@ func NodeToProto(n *Node) (*proto.Node, error) {
5151
allowedIPs[i] = string(s)
5252
}
5353
return &proto.Node{
54-
Id: int64(n.ID),
55-
AsOf: timestamppb.New(n.AsOf),
56-
Key: k,
57-
Disco: string(disco),
54+
Id: int64(n.ID),
55+
AsOf: timestamppb.New(n.AsOf),
56+
Key: k,
57+
Disco: string(disco),
58+
// #nosec G115 - Safe conversion as DERP region IDs are small integers expected to be within int32 range
5859
PreferredDerp: int32(n.PreferredDERP),
5960
DerpLatency: n.DERPLatency,
6061
DerpForcedWebsocket: derpForcedWebsocket,
@@ -191,14 +192,16 @@ func DERPNodeToProto(node *tailcfg.DERPNode) *proto.DERPMap_Region_Node {
191192
}
192193

193194
return &proto.DERPMap_Region_Node{
194-
Name: node.Name,
195-
RegionId: int64(node.RegionID),
196-
HostName: node.HostName,
197-
CertName: node.CertName,
198-
Ipv4: node.IPv4,
199-
Ipv6: node.IPv6,
200-
StunPort: int32(node.STUNPort),
201-
StunOnly: node.STUNOnly,
195+
Name: node.Name,
196+
RegionId: int64(node.RegionID),
197+
HostName: node.HostName,
198+
CertName: node.CertName,
199+
Ipv4: node.IPv4,
200+
Ipv6: node.IPv6,
201+
// #nosec G115 - Safe conversion as STUN port is within int32 range (0-65535)
202+
StunPort: int32(node.STUNPort),
203+
StunOnly: node.STUNOnly,
204+
// #nosec G115 - Safe conversion as DERP port is within int32 range (0-65535)
202205
DerpPort: int32(node.DERPPort),
203206
InsecureForTests: node.InsecureForTests,
204207
ForceHttp: node.ForceHTTP,

vpn/router.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func convertToIPV4Route(route netip.Prefix) *NetworkSettingsRequest_IPv4Settings
115115

116116
func convertToIPV6Route(route netip.Prefix) *NetworkSettingsRequest_IPv6Settings_IPv6Route {
117117
return &NetworkSettingsRequest_IPv6Settings_IPv6Route{
118-
Destination: route.Addr().String(),
118+
Destination: route.Addr().String(),
119119
// #nosec G115 - Safe conversion as prefix lengths are always within uint32 range (0-128)
120120
PrefixLength: uint32(route.Bits()),
121121
Router: "", // N/A

vpn/serdes.go

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ func (s *serdes[S, _, _]) sendLoop() {
8181
s.logger.Critical(s.ctx, "failed to marshal message", slog.Error(err))
8282
return
8383
}
84+
// #nosec G115 - Safe conversion as protobuf message length is expected to be within uint32 range
8485
if err := binary.Write(s.conn, binary.BigEndian, uint32(len(mb))); err != nil {
8586
s.logger.Debug(s.ctx, "failed to write length", slog.Error(err))
8687
return

vpn/speaker_internal_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ func TestSpeaker_RawPeer(t *testing.T) {
7474
msgBuf := make([]byte, msgLen)
7575
n, err = mp.Read(msgBuf)
7676
require.NoError(t, err)
77+
// #nosec G115 - Safe conversion of read bytes count to uint32 for comparison with message length
7778
require.Equal(t, msgLen, uint32(n))
7879
msg := new(TunnelMessage)
7980
err = proto.Unmarshal(msgBuf, msg)

0 commit comments

Comments
 (0)