plugin: fix gosec G115 integer overflow warnings (#7799)

Fix integer overflow conversion warnings (G115) by adding appropriate
suppressions where values are provably bounded.

Fixes: https://github.com/coredns/coredns/issues/7793

Changes:
- Updated 56 G115 annotations to use consistent // #nosec G115 format
- Added 2 //nolint:gosec suppressions for conditional expressions
- Removed G115 exclusion from golangci.yml (now explicitly handled per-line)

Suppressions justify why each conversion is safe (e.g., port numbers
are bounded 1-65535, DNS TTL limits, pool lengths, etc.)

Signed-off-by: Azeez Syed <syedazeez337@gmail.com>
This commit is contained in:
Syed Azeez
2026-01-01 13:50:29 +05:30
committed by GitHub
parent be934b2b06
commit 7b38eb8625
26 changed files with 58 additions and 59 deletions

View File

@@ -42,9 +42,6 @@ linters:
- perfsprint
- gosec
settings:
gosec:
excludes:
- G115
govet:
enable:
- nilness

View File

@@ -53,7 +53,7 @@ func (w *DoQWriter) Close() error {
// AddPrefix adds a 2-byte prefix with the DNS message length.
func AddPrefix(b []byte) (m []byte) {
m = make([]byte, 2+len(b))
binary.BigEndian.PutUint16(m, uint16(len(b)))
binary.BigEndian.PutUint16(m, uint16(len(b))) // #nosec G115 -- DNS message length fits in uint16
copy(m[2:], b)
return m

View File

@@ -101,7 +101,7 @@ func (s *ServergRPC) Serve(l net.Listener) error {
// Only set MaxConcurrentStreams if not unbounded (0)
if s.maxStreams > 0 {
serverOpts = append(serverOpts, grpc.MaxConcurrentStreams(uint32(s.maxStreams)))
serverOpts = append(serverOpts, grpc.MaxConcurrentStreams(uint32(s.maxStreams))) // #nosec G115 -- maxStreams is bounded
}
if s.Tracer() != nil {

View File

@@ -363,7 +363,8 @@ func readDOQMessage(r io.Reader) ([]byte, error) {
// A client or server receives a STREAM FIN before receiving all the bytes
// for a message indicated in the 2-octet length field.
// See https://www.rfc-editor.org/rfc/rfc9250#section-4.3.3-2.2
if size != uint16(len(buf)) {
//nolint:gosec
if size != uint16(len(buf)) { // #nosec G115 -- buf length fits in uint16
return nil, fmt.Errorf("message size does not match 2-byte prefix")
}

View File

@@ -139,7 +139,7 @@ func (h *Azure) updateZones(ctx context.Context) error {
func updateZoneFromPublicResourceSet(recordSet publicdns.RecordSetListResultPage, newZ *file.Zone) {
for _, result := range *(recordSet.Response().Value) {
resultFqdn := *(result.Fqdn)
resultTTL := uint32(*(result.TTL))
resultTTL := uint32(*(result.TTL)) // #nosec G115 -- Azure API guarantees TTL fits in uint32
if result.ARecords != nil {
for _, A := range *(result.ARecords) {
a := &dns.A{Hdr: dns.RR_Header{Name: resultFqdn, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: resultTTL},
@@ -159,7 +159,7 @@ func updateZoneFromPublicResourceSet(recordSet publicdns.RecordSetListResultPage
if result.MxRecords != nil {
for _, MX := range *(result.MxRecords) {
mx := &dns.MX{Hdr: dns.RR_Header{Name: resultFqdn, Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: resultTTL},
Preference: uint16(*(MX.Preference)),
Preference: uint16(*(MX.Preference)), // #nosec G115 -- MX preference fits in uint16
Mx: dns.Fqdn(*(MX.Exchange))}
newZ.Insert(mx)
}
@@ -176,9 +176,9 @@ func updateZoneFromPublicResourceSet(recordSet publicdns.RecordSetListResultPage
if result.SrvRecords != nil {
for _, SRV := range *(result.SrvRecords) {
srv := &dns.SRV{Hdr: dns.RR_Header{Name: resultFqdn, Rrtype: dns.TypeSRV, Class: dns.ClassINET, Ttl: resultTTL},
Priority: uint16(*(SRV.Priority)),
Weight: uint16(*(SRV.Weight)),
Port: uint16(*(SRV.Port)),
Priority: uint16(*(SRV.Priority)), // #nosec G115 -- SRV priority fits in uint16
Weight: uint16(*(SRV.Weight)), // #nosec G115 -- SRV weight fits in uint16
Port: uint16(*(SRV.Port)), // #nosec G115 -- Port fits in uint16
Target: dns.Fqdn(*(SRV.Target))}
newZ.Insert(srv)
}
@@ -203,11 +203,11 @@ func updateZoneFromPublicResourceSet(recordSet publicdns.RecordSetListResultPage
if result.SoaRecord != nil {
SOA := result.SoaRecord
soa := &dns.SOA{Hdr: dns.RR_Header{Name: resultFqdn, Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: resultTTL},
Minttl: uint32(*(SOA.MinimumTTL)),
Expire: uint32(*(SOA.ExpireTime)),
Retry: uint32(*(SOA.RetryTime)),
Refresh: uint32(*(SOA.RefreshTime)),
Serial: uint32(*(SOA.SerialNumber)),
Minttl: uint32(*(SOA.MinimumTTL)), // #nosec G115 -- DNS protocol mandates uint32 for SOA
Expire: uint32(*(SOA.ExpireTime)), // #nosec G115 -- DNS protocol mandates uint32 for SOA
Retry: uint32(*(SOA.RetryTime)), // #nosec G115 -- DNS protocol mandates uint32 for SOA
Refresh: uint32(*(SOA.RefreshTime)), // #nosec G115 -- DNS protocol mandates uint32 for SOA
Serial: uint32(*(SOA.SerialNumber)), // #nosec G115 -- DNS protocol mandates uint32 for SOA
Mbox: dns.Fqdn(*(SOA.Email)),
Ns: *(SOA.Host)}
newZ.Insert(soa)
@@ -225,7 +225,7 @@ func updateZoneFromPublicResourceSet(recordSet publicdns.RecordSetListResultPage
func updateZoneFromPrivateResourceSet(recordSet privatedns.RecordSetListResultPage, newZ *file.Zone) {
for _, result := range *(recordSet.Response().Value) {
resultFqdn := *(result.Fqdn)
resultTTL := uint32(*(result.TTL))
resultTTL := uint32(*(result.TTL)) // #nosec G115 -- Azure API guarantees TTL fits in uint32
if result.ARecords != nil {
for _, A := range *(result.ARecords) {
a := &dns.A{Hdr: dns.RR_Header{Name: resultFqdn, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: resultTTL},
@@ -244,7 +244,7 @@ func updateZoneFromPrivateResourceSet(recordSet privatedns.RecordSetListResultPa
if result.MxRecords != nil {
for _, MX := range *(result.MxRecords) {
mx := &dns.MX{Hdr: dns.RR_Header{Name: resultFqdn, Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: resultTTL},
Preference: uint16(*(MX.Preference)),
Preference: uint16(*(MX.Preference)), // #nosec G115 -- MX preference fits in uint16
Mx: dns.Fqdn(*(MX.Exchange))}
newZ.Insert(mx)
}
@@ -261,9 +261,9 @@ func updateZoneFromPrivateResourceSet(recordSet privatedns.RecordSetListResultPa
if result.SrvRecords != nil {
for _, SRV := range *(result.SrvRecords) {
srv := &dns.SRV{Hdr: dns.RR_Header{Name: resultFqdn, Rrtype: dns.TypeSRV, Class: dns.ClassINET, Ttl: resultTTL},
Priority: uint16(*(SRV.Priority)),
Weight: uint16(*(SRV.Weight)),
Port: uint16(*(SRV.Port)),
Priority: uint16(*(SRV.Priority)), // #nosec G115 -- SRV priority fits in uint16
Weight: uint16(*(SRV.Weight)), // #nosec G115 -- SRV weight fits in uint16
Port: uint16(*(SRV.Port)), // #nosec G115 -- Port fits in uint16
Target: dns.Fqdn(*(SRV.Target))}
newZ.Insert(srv)
}
@@ -280,11 +280,11 @@ func updateZoneFromPrivateResourceSet(recordSet privatedns.RecordSetListResultPa
if result.SoaRecord != nil {
SOA := result.SoaRecord
soa := &dns.SOA{Hdr: dns.RR_Header{Name: resultFqdn, Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: resultTTL},
Minttl: uint32(*(SOA.MinimumTTL)),
Expire: uint32(*(SOA.ExpireTime)),
Retry: uint32(*(SOA.RetryTime)),
Refresh: uint32(*(SOA.RefreshTime)),
Serial: uint32(*(SOA.SerialNumber)),
Minttl: uint32(*(SOA.MinimumTTL)), // #nosec G115 -- DNS protocol mandates uint32 for SOA
Expire: uint32(*(SOA.ExpireTime)), // #nosec G115 -- DNS protocol mandates uint32 for SOA
Retry: uint32(*(SOA.RetryTime)), // #nosec G115 -- DNS protocol mandates uint32 for SOA
Refresh: uint32(*(SOA.RefreshTime)), // #nosec G115 -- DNS protocol mandates uint32 for SOA
Serial: uint32(*(SOA.SerialNumber)), // #nosec G115 -- DNS protocol mandates uint32 for SOA
Mbox: dns.Fqdn(*(SOA.Email)),
Ns: dns.Fqdn(*(SOA.Host))}
newZ.Insert(soa)

View File

@@ -18,7 +18,7 @@ type Bufsize struct {
// ServeDNS implements the plugin.Handler interface.
func (buf Bufsize) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
if option := r.IsEdns0(); option != nil && int(option.UDPSize()) > buf.Size {
option.SetUDPSize(uint16(buf.Size))
option.SetUDPSize(uint16(buf.Size)) // #nosec G115 -- buffer size fits in uint16
}
return plugin.NextOrFailure(buf.Name(), buf.Next, ctx, w, r)
}

View File

@@ -82,7 +82,7 @@ func (i *item) toMsg(m *dns.Msg, now time.Time, do bool, ad bool) *dns.Msg {
m1.RecursionAvailable = i.RecursionAvailable
m1.Rcode = i.Rcode
ttl := uint32(i.ttl(now))
ttl := uint32(i.ttl(now)) // #nosec G115 -- ttl is bounded by DNS TTL limits
m1.Answer = filterRRSlice(i.Answer, ttl, true)
m1.Ns = filterRRSlice(i.Ns, ttl, true)
m1.Extra = filterRRSlice(i.Extra, ttl, true)

View File

@@ -167,8 +167,8 @@ func (d Dnssec) get(key uint64, server string) ([]dns.RR, bool) {
}
func incepExpir(now time.Time) (uint32, uint32) {
incep := uint32(now.Add(-3 * time.Hour).Unix()) // -(2+1) hours, be sure to catch daylight saving time and such
expir := uint32(now.Add(eightDays).Unix()) // sign for 8 days
incep := uint32(now.Add(-3 * time.Hour).Unix()) // #nosec G115 -- DNSSEC inception, Year 2106 problem accepted // -(2+1) hours, be sure to catch daylight saving time and such
expir := uint32(now.Add(eightDays).Unix()) // #nosec G115 -- DNSSEC expiration, Year 2106 problem accepted // sign for 8 days
return incep, expir
}

View File

@@ -23,7 +23,7 @@ func SetQueryAddress(t *tap.Message, addr net.Addr) error {
t.SocketProtocol = &protoTCP
t.QueryAddress = a.IP
p := uint32(a.Port)
p := uint32(a.Port) // #nosec G115 -- Port is inherently bounded (1-65535)
t.QueryPort = &p
if a.IP.To4() == nil {
@@ -34,7 +34,7 @@ func SetQueryAddress(t *tap.Message, addr net.Addr) error {
t.SocketProtocol = &protoUDP
t.QueryAddress = a.IP
p := uint32(a.Port)
p := uint32(a.Port) // #nosec G115 -- Port is inherently bounded (1-65535)
t.QueryPort = &p
if a.IP.To4() == nil {
@@ -54,7 +54,7 @@ func SetResponseAddress(t *tap.Message, addr net.Addr) error {
t.SocketProtocol = &protoTCP
t.ResponseAddress = a.IP
p := uint32(a.Port)
p := uint32(a.Port) // #nosec G115 -- Port is inherently bounded (1-65535)
t.ResponsePort = &p
if a.IP.To4() == nil {
@@ -65,7 +65,7 @@ func SetResponseAddress(t *tap.Message, addr net.Addr) error {
t.SocketProtocol = &protoUDP
t.ResponseAddress = a.IP
p := uint32(a.Port)
p := uint32(a.Port) // #nosec G115 -- Port is inherently bounded (1-65535)
t.ResponsePort = &p
if a.IP.To4() == nil {
@@ -79,16 +79,16 @@ func SetResponseAddress(t *tap.Message, addr net.Addr) error {
// SetQueryTime sets the time of the query in t.
func SetQueryTime(t *tap.Message, ti time.Time) {
qts := uint64(ti.Unix())
qtn := uint32(ti.Nanosecond())
qts := uint64(ti.Unix()) // #nosec G115 -- Unix time fits in uint64
qtn := uint32(ti.Nanosecond()) // #nosec G115 -- Nanoseconds (0-999999999) fit in uint32
t.QueryTimeSec = &qts
t.QueryTimeNsec = &qtn
}
// SetResponseTime sets the time of the response in t.
func SetResponseTime(t *tap.Message, ti time.Time) {
rts := uint64(ti.Unix())
rtn := uint32(ti.Nanosecond())
rts := uint64(ti.Unix()) // #nosec G115 -- Unix time fits in uint64
rtn := uint32(ti.Nanosecond()) // #nosec G115 -- Nanoseconds (0-999999999) fit in uint32
t.ResponseTimeSec = &rts
t.ResponseTimeNsec = &rtn
}

View File

@@ -190,7 +190,7 @@ func (e *Etcd) TTL(kv *mvccpb.KeyValue, serv *msg.Service) uint32 {
leaseTTL = maxTTL64
}
etcdTTL = uint32(leaseTTL)
etcdTTL = uint32(leaseTTL) // #nosec G115 -- leaseTTL is bounded by minTTL64/maxTTL64
}
}

View File

@@ -44,7 +44,7 @@ func (s *Service) NewSRV(name string, weight uint16) *dns.SRV {
}
return &dns.SRV{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeSRV, Class: dns.ClassINET, Ttl: s.TTL},
Priority: uint16(s.Priority), Weight: weight, Port: uint16(s.Port), Target: host}
Priority: uint16(s.Priority), Weight: weight, Port: uint16(s.Port), Target: host} // #nosec G115 -- Priority and Port fit in uint16
}
// NewMX returns a new MX record based on the Service.
@@ -55,7 +55,7 @@ func (s *Service) NewMX(name string) *dns.MX {
}
return &dns.MX{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: s.TTL},
Preference: uint16(s.Priority), Mx: host}
Preference: uint16(s.Priority), Mx: host} // #nosec G115 -- MX preference fits in uint16
}
// NewA returns a new A record based on the Service.

View File

@@ -8,7 +8,7 @@ import (
// Serial returns the serial number to use.
func (e *Etcd) Serial(state request.Request) uint32 {
return uint32(time.Now().Unix())
return uint32(time.Now().Unix()) // #nosec G115 -- Unix time to SOA serial, Year 2106 problem accepted
}
// MinTTL returns the minimal TTL.

View File

@@ -156,7 +156,8 @@ func Parse(f io.Reader, origin, fileName string, serial int64) (*Zone, error) {
// -1 is valid serial is we failed to load the file on startup.
if serial >= 0 && s.Serial == uint32(serial) { // same serial
//nolint:gosec
if serial >= 0 && s.Serial == uint32(serial) { // #nosec G115 -- serial is validated non-negative, fits in uint32
return nil, &serialErr{err: "no change in SOA serial", origin: origin, zone: fileName, serial: serial}
}
}

View File

@@ -92,7 +92,7 @@ Transfer:
if z.SOA == nil {
return true, Err
}
return less(z.SOA.Serial, uint32(serial)), Err
return less(z.SOA.Serial, uint32(serial)), Err // #nosec G115 -- serial fits in uint32 per DNS RFC
}
// less returns true of a is smaller than b when taking RFC 1982 serial arithmetic into account.

View File

@@ -47,7 +47,7 @@ type roundRobin struct {
func (r *roundRobin) String() string { return "round_robin" }
func (r *roundRobin) List(p []*proxy.Proxy) []*proxy.Proxy {
poolLen := uint32(len(p))
poolLen := uint32(len(p)) // #nosec G115 -- pool length is small
i := atomic.AddUint32(&r.robin, 1) % poolLen
robin := []*proxy.Proxy{p[i]}

View File

@@ -51,7 +51,7 @@ func (r *roundRobin) List(p []*Proxy) []*Proxy {
if len(p) == 0 {
return nil
}
poolLen := uint32(len(p))
poolLen := uint32(len(p)) // #nosec G115 -- pool length is small
i := atomic.AddUint32(&r.robin, 1) % poolLen
robin := []*Proxy{p[i]}

View File

@@ -211,7 +211,7 @@ func (k *Kubernetes) ExternalServices(zone string, headless bool) (services []ms
// ExternalSerial returns the serial of the external zone
func (k *Kubernetes) ExternalSerial(string) uint32 {
return uint32(k.APIConn.Modified(ModifiedExternal))
return uint32(k.APIConn.Modified(ModifiedExternal)) // #nosec G115 -- Unix time to SOA serial
}
// ExternalReverse does a reverse lookup for the external IPs

View File

@@ -668,9 +668,9 @@ func (k *Kubernetes) findMultiClusterServices(r recordRequest, zone string) (ser
// Serial return the SOA serial.
func (k *Kubernetes) Serial(state request.Request) uint32 {
if !k.isMultiClusterZone(state.Zone) {
return uint32(k.APIConn.Modified(ModifiedInternal))
return uint32(k.APIConn.Modified(ModifiedInternal)) // #nosec G115 -- Unix time to SOA serial
} else {
return uint32(k.APIConn.Modified(ModifiedMultiCluster))
return uint32(k.APIConn.Modified(ModifiedMultiCluster)) // #nosec G115 -- Unix time to SOA serial
}
}

View File

@@ -56,7 +56,7 @@ func (r *randomUint) randInit() {
}
func (r *randomUint) randUint(limit uint) uint {
return uint(r.rn.Intn(int(limit)))
return uint(r.rn.Intn(int(limit))) // #nosec G115 -- limit is bounded by RR count
}
func weightedShuffle(res *dns.Msg, w *weightedRR) *dns.Msg {

View File

@@ -11,7 +11,7 @@ func addSRVRecord(m *dns.Msg, s *api.ServiceRegistration, header dns.RR_Header,
srvRecord := &dns.SRV{
Hdr: header,
Target: originalQName,
Port: uint16(s.Port),
Port: uint16(s.Port), // #nosec G115 -- port numbers are bounded (1-65535)
Priority: 10,
Weight: 10,
}

View File

@@ -19,7 +19,7 @@ func init() { plugin.Register(pluginName, setup) }
// for parsing any extra options the nomad plugin may have. The first token this function sees is "nomad".
func setup(c *caddy.Controller) error {
n := &Nomad{
ttl: uint32(defaultTTL),
ttl: uint32(defaultTTL), // #nosec G115 -- defaultTTL is a constant that fits in uint32
clients: make([]*nomad.Client, 0),
current: -1,
}

View File

@@ -123,7 +123,7 @@ func (p *Proxy) Connect(ctx context.Context, state request.Request, opts Options
}
// Set buffer size correctly for this client.
pc.c.UDPSize = max(uint16(state.Size()), 512)
pc.c.UDPSize = max(uint16(state.Size()), 512) // #nosec G115 -- UDP size fits in uint16
pc.c.SetWriteDeadline(time.Now().Add(maxTimeout))
// records the origin Id before upstream.

View File

@@ -199,7 +199,7 @@ func isValidTTL(v string) (uint32, uint32, bool) {
// reject invalid range
return 0, 0, false
}
return uint32(min), uint32(max), true
return uint32(min), uint32(max), true // #nosec G115 -- min/max parsed with 32-bit limit
}
return 0, 0, false
}

View File

@@ -44,7 +44,7 @@ func (s *Signer) Sign(now time.Time) (*file.Zone, error) {
mttl := z.SOA.Minttl
ttl := z.SOA.Header().Ttl
inception, expiration := lifetime(now, s.jitterIncep, s.jitterExpir)
z.SOA.Serial = uint32(now.Unix())
z.SOA.Serial = uint32(now.Unix()) // #nosec G115 -- Unix time to SOA serial, Year 2106 problem accepted
for _, pair := range s.keys {
pair.Public.Header().Ttl = ttl // set TTL on key so it matches the RRSIG.
@@ -200,7 +200,7 @@ func (s *Signer) refresh(val time.Duration) {
}
func lifetime(now time.Time, jitterInception, jitterExpiration time.Duration) (uint32, uint32) {
incep := uint32(now.Add(durationSignatureInceptionHours).Add(jitterInception).Unix())
expir := uint32(now.Add(durationSignatureExpireDays).Add(jitterExpiration).Unix())
incep := uint32(now.Add(durationSignatureInceptionHours).Add(jitterInception).Unix()) // #nosec G115 -- DNSSEC signature inception, Year 2106 problem accepted
expir := uint32(now.Add(durationSignatureExpireDays).Add(jitterExpiration).Unix()) // #nosec G115 -- DNSSEC signature expiration, Year 2106 problem accepted
return incep, expir
}

View File

@@ -117,7 +117,7 @@ func OPT(bufsize int, do bool) *dns.OPT {
o.Hdr.Name = "."
o.Hdr.Rrtype = dns.TypeOPT
o.SetVersion(0)
o.SetUDPSize(uint16(bufsize))
o.SetUDPSize(uint16(bufsize)) // #nosec G115 -- buffer size fits in uint16
if do {
o.SetDo()
}

View File

@@ -126,7 +126,7 @@ func (r *restoreTsigWriter) WriteMsg(m *dns.Msg) error {
repTSIG.TimeSigned = r.reqTSIG.TimeSigned
b := make([]byte, 8)
// TimeSigned is network byte order.
binary.BigEndian.PutUint64(b, uint64(time.Now().Unix()))
binary.BigEndian.PutUint64(b, uint64(time.Now().Unix())) // #nosec G115 -- Unix time fits in uint64
// truncate to 48 least significant bits (network order 6 rightmost bytes)
repTSIG.OtherData = hex.EncodeToString(b[2:])
repTSIG.OtherLen = 6