diff --git a/.github/workflows/boulder-ci.yml b/.github/workflows/boulder-ci.yml index d93582d0054..2d031843b0d 100644 --- a/.github/workflows/boulder-ci.yml +++ b/.github/workflows/boulder-ci.yml @@ -36,7 +36,7 @@ jobs: matrix: # Add additional docker image tags here and all tests will be run with the additional image. BOULDER_TOOLS_TAG: - - go1.26.6_2026-08-13 + - go1.26.6_2026-08-21 # Tests command definitions. Use the entire "docker compose" command you want to run. tests: # Run ./test.sh --help for a description of each of the flags. diff --git a/ca/ca.go b/ca/ca.go index ebad4c709cf..b8f6af14d13 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -481,7 +481,7 @@ func (ca *certificateAuthorityImpl) generateSerialNumber() *big.Int { // rand.Read is guaranteed since Go 1.24 not to return error (it crashes the program instead) // https://tip.golang.org/doc/go1.24#cryptorandpkgcryptorand // https://pkg.go.dev/crypto/rand@master#Read - rand.Read(serialBytes[1:]) //nolint:errcheck //rand.Read is infallible + rand.Read(serialBytes[1:]) serialBigInt := big.NewInt(0) serialBigInt = serialBigInt.SetBytes(serialBytes) diff --git a/cmd/boulder-ca/main.go b/cmd/boulder-ca/main.go index dee21261ffa..660ba767502 100644 --- a/cmd/boulder-ca/main.go +++ b/cmd/boulder-ca/main.go @@ -53,19 +53,13 @@ type Config struct { Issuers []issuance.IssuerConfig `validate:"min=1,dive"` } - // What digits we should prepend to serials after randomly generating them. - // Deprecated: Use SerialPrefixHex instead. - SerialPrefix int `validate:"required_without=SerialPrefixHex,omitempty,min=1,max=127"` - // SerialPrefixHex is the hex string to prepend to serials after randomly // generating them. The minimum value is "01" to ensure that at least // one bit in the prefix byte is set. The maximum value is "7f" to // ensure that the first bit in the prefix byte is not set. The validate // library cannot enforce mix/max values on strings, so that is done in // NewCertificateAuthorityImpl. - // - // TODO(#7213): Replace `required_without` with `required` when SerialPrefix is removed. - SerialPrefixHex string `validate:"required_without=SerialPrefix,omitempty,hexadecimal,len=2"` + SerialPrefixHex string `validate:"required,omitempty,hexadecimal,len=2"` // MaxNames is the maximum number of subjectAltNames in a single cert. // The value supplied MUST be greater than 0 and no more than 100. These @@ -134,12 +128,9 @@ func main() { c.CA.DebugAddr = *debugAddr } - serialPrefix := byte(c.CA.SerialPrefix) - if c.CA.SerialPrefixHex != "" { - parsedSerialPrefix, err := strconv.ParseUint(c.CA.SerialPrefixHex, 16, 8) - cmd.FailOnError(err, "Couldn't convert SerialPrefixHex to int") - serialPrefix = byte(parsedSerialPrefix) - } + parsedSerialPrefix, err := strconv.ParseUint(c.CA.SerialPrefixHex, 16, 8) + cmd.FailOnError(err, "Couldn't convert SerialPrefixHex to int") + serialPrefix := byte(parsedSerialPrefix) scope, logger, oTelShutdown := cmd.StatsAndLogging(c.Syslog, c.OpenTelemetry, c.CA.DebugAddr) defer oTelShutdown(context.Background()) diff --git a/cmd/shell_test.go b/cmd/shell_test.go index 16cc8c114a3..defa7836e7a 100644 --- a/cmd/shell_test.go +++ b/cmd/shell_test.go @@ -278,7 +278,7 @@ func TestFailExit(t *testing.T) { return } - cmd := exec.Command(os.Args[0], "-test.run=TestFailExit") + cmd := exec.Command(os.Args[0], "-test.run=TestFailExit") //nolint:gosec // os.Args is untrusted but we're okay with that in test code cmd.Env = append(os.Environ(), "TIME_TO_DIE=1") output, err := cmd.CombinedOutput() test.AssertError(t, err, "running a failing program") @@ -304,7 +304,7 @@ func TestPanicStackTrace(t *testing.T) { return } - cmd := exec.Command(os.Args[0], "-test.run=TestPanicStackTrace") + cmd := exec.Command(os.Args[0], "-test.run=TestPanicStackTrace") //nolint:gosec // os.Args is untrusted but we're okay with that in test code cmd.Env = append(os.Environ(), "AT_THE_DISCO=1") output, err := cmd.CombinedOutput() test.AssertError(t, err, "running a failing program") diff --git a/linter/lints/cpcps/helpers_test.go b/linter/lints/cpcps/helpers_test.go index bac03d60d39..696e1e385cf 100644 --- a/linter/lints/cpcps/helpers_test.go +++ b/linter/lints/cpcps/helpers_test.go @@ -27,6 +27,7 @@ import ( zpkix "github.com/zmap/zcrypto/x509/pkix" "github.com/zmap/zlint/v3/lint" "github.com/zmap/zlint/v3/util" + "golang.org/x/crypto/cryptobyte" ) // testKey generates an ECDSA key on the given curve. @@ -152,18 +153,23 @@ func testSCT(logID [32]byte) []byte { // containing one fake SCT per given log ID. func testSCTListExtension(t *testing.T, logIDs ...[32]byte) pkix.Extension { t.Helper() - var list []byte - for _, logID := range logIDs { - sct := testSCT(logID) - list = append(list, byte(len(sct)>>8), byte(len(sct))) - list = append(list, sct...) - } - full := append([]byte{byte(len(list) >> 8), byte(len(list))}, list...) - value, err := asn1.Marshal(full) - if err != nil { - t.Fatalf("marshalling SCT list: %s", err) + + var sctList cryptobyte.Builder + sctList.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) { + for _, logID := range logIDs { + child.AddUint16LengthPrefixed(func(child *cryptobyte.Builder) { + child.AddBytes(testSCT(logID)) + }) + } + }) + + var extnValue cryptobyte.Builder + extnValue.AddASN1OctetString(sctList.BytesOrPanic()) + + return pkix.Extension{ + Id: asn1.ObjectIdentifier(util.TimestampOID), + Value: extnValue.BytesOrPanic(), } - return pkix.Extension{Id: asn1.ObjectIdentifier(util.TimestampOID), Value: value} } // testLeafTemplate returns a template matching the Subscriber (Server) diff --git a/observer/monitor.go b/observer/monitor.go index 7784fddfa6d..8b6c12f073a 100644 --- a/observer/monitor.go +++ b/observer/monitor.go @@ -30,7 +30,7 @@ func (m monitor) start(ctx context.Context, logger blog.Logger) { for { go func() { - ctx, cancel := context.WithTimeout(context.Background(), m.period/2) + ctx, cancel := context.WithTimeout(ctx, m.period/2) defer cancel() // Attempt to probe the configured target. diff --git a/publisher/publisher.go b/publisher/publisher.go index de88bff92b4..3f4c3270760 100644 --- a/publisher/publisher.go +++ b/publisher/publisher.go @@ -325,14 +325,14 @@ func (pub *Impl) singleLogSubmit( "http_status": "", }).Observe(took) - threshold := uint64(time.Now().Add(time.Minute).UnixMilli()) //nolint: gosec // Current-ish timestamp is guaranteed to fit in a uint64 + threshold := uint64(time.Now().Add(time.Minute).UnixMilli()) if sct.Timestamp > threshold { return nil, fmt.Errorf("SCT Timestamp was too far in the future (%d > %d)", sct.Timestamp, threshold) } // For regular certificates, we could get an old SCT, but that shouldn't // happen for precertificates. - threshold = uint64(time.Now().Add(-10 * time.Minute).UnixMilli()) //nolint: gosec // Current-ish timestamp is guaranteed to fit in a uint64 + threshold = uint64(time.Now().Add(-10 * time.Minute).UnixMilli()) if kind != pubpb.SubmissionType_final && sct.Timestamp < threshold { return nil, fmt.Errorf("SCT Timestamp was too far in the past (%d < %d)", sct.Timestamp, threshold) } @@ -365,7 +365,7 @@ func CreateTestingSignedSCT(req []string, k *ecdsa.PrivateKey, precert bool, tim // Sign the SCT rawKey, _ := x509.MarshalPKIXPublicKey(&k.PublicKey) logID := sha256.Sum256(rawKey) - timestampMillis := uint64(timestamp.UnixMilli()) //nolint: gosec // Current-ish timestamp is guaranteed to fit in a uint64 + timestampMillis := uint64(timestamp.UnixMilli()) serialized, _ := ct.SerializeSCTSignatureInput(ct.SignedCertificateTimestamp{ SCTVersion: ct.V1, LogID: ct.LogID{KeyID: logID}, diff --git a/ratelimits/limiter_test.go b/ratelimits/limiter_test.go index 47427e3c4c5..f8bcfb02a54 100644 --- a/ratelimits/limiter_test.go +++ b/ratelimits/limiter_test.go @@ -49,7 +49,7 @@ func setup(t *testing.T) (context.Context, map[string]*Limiter, *TransactionBuil // runs. randIP := make(net.IP, 4) for i := range 4 { - randIP[i] = byte(rand.IntN(256)) + randIP[i] = byte(rand.IntN(256)) //nolint:gosec // we know the integer is byte-sized } // Construct a limiter for each source. diff --git a/sa/model_test.go b/sa/model_test.go index 2640076dac6..8b7bdcd4d45 100644 --- a/sa/model_test.go +++ b/sa/model_test.go @@ -375,7 +375,7 @@ func TestIncidentSerialModel(t *testing.T) { testIncidentsDbMap, err := DBMapForTest(vars.DBConnIncidentsFullPerms) test.AssertNotError(t, err, "Couldn't create test dbMap") - defer test.ResetIncidentsTestDatabase(t) + t.Cleanup(test.ResetIncidentsTestDatabase(t)) // Inserting and retrieving a row with only the serial populated should work. _, err = testIncidentsDbMap.ExecContext(ctx, diff --git a/sa/sa_test.go b/sa/sa_test.go index ea644b327d7..a621e8fdbb6 100644 --- a/sa/sa_test.go +++ b/sa/sa_test.go @@ -2918,7 +2918,7 @@ func TestIncidentsForSerial(t *testing.T) { testIncidentsDbMap, err := DBMapForTest(vars.DBConnIncidentsFullPerms) test.AssertNotError(t, err, "Couldn't create test dbMap") - defer test.ResetIncidentsTestDatabase(t) + t.Cleanup(test.ResetIncidentsTestDatabase(t)) weekAgo := sa.clk.Now().Add(-time.Hour * 24 * 7) @@ -3033,7 +3033,7 @@ func TestSerialsForIncident(t *testing.T) { testIncidentsDbMap, err := DBMapForTest(vars.DBConnIncidentsFullPerms) test.AssertNotError(t, err, "Couldn't create test dbMap") - defer test.ResetIncidentsTestDatabase(t) + t.Cleanup(test.ResetIncidentsTestDatabase(t)) // Request serials from a malformed incident table name. mockServerStream := &fakeServerStream[sapb.IncidentSerial]{} @@ -3900,7 +3900,7 @@ func TestUnpauseAccount(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - defer test.ResetBoulderTestDatabase(t) + t.Cleanup(test.ResetBoulderTestDatabase(t)) // Setup table state. for _, state := range tt.state { @@ -4145,7 +4145,7 @@ func TestPauseIdentifiers(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - defer test.ResetBoulderTestDatabase(t) + t.Cleanup(test.ResetBoulderTestDatabase(t)) // Setup table state. for _, state := range tt.state { @@ -4283,7 +4283,7 @@ func TestCheckIdentifiersPaused(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - defer test.ResetBoulderTestDatabase(t) + t.Cleanup(test.ResetBoulderTestDatabase(t)) // Setup table state. for _, state := range tt.state { @@ -4389,7 +4389,7 @@ func TestGetPausedIdentifiers(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - defer test.ResetBoulderTestDatabase(t) + t.Cleanup(test.ResetBoulderTestDatabase(t)) // Setup table state. for _, state := range tt.state { diff --git a/salesforce/pardot_test.go b/salesforce/pardot_test.go index 7407b1d5265..d46ae3cea5c 100644 --- a/salesforce/pardot_test.go +++ b/salesforce/pardot_test.go @@ -10,10 +10,12 @@ import ( "time" "github.com/jmhodges/clock" + "github.com/letsencrypt/boulder/test" ) func defaultTokenHandler(w http.ResponseWriter, r *http.Request) { + //nolint:gosec // G117: The "AccessToken" field is not a real access token err := json.NewEncoder(w).Encode(oauthTokenResp{ AccessToken: "dummy", ExpiresIn: 3600, @@ -113,6 +115,7 @@ func TestSendContactTokenExpiry(t *testing.T) { token = "old_token" tokenRetrieved = true } + //nolint:gosec // G117: The "AccessToken" field is not a real access token err := json.NewEncoder(w).Encode(oauthTokenResp{ AccessToken: token, ExpiresIn: 3600, diff --git a/sfe/forms/fields.go b/sfe/forms/fields.go index 72925d6c457..11a0c56fc9c 100644 --- a/sfe/forms/fields.go +++ b/sfe/forms/fields.go @@ -90,14 +90,14 @@ func (field DropdownField) RenderField() template.HTML { reqAttr = `required="required"` } var b strings.Builder - b.WriteString(fmt.Sprintf(` + fmt.Fprintf(&b, `