diff --git a/.golangci.yaml b/.golangci.yaml index 5b3e06c655..1b44c8e06a 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -17,7 +17,7 @@ linters: #- gocyclo #- godot - gofumpt - #- gosec + - gosec - gosimple - govet - ineffassign @@ -85,6 +85,12 @@ linters-settings: - style gofumpt: extra-rules: true + gosec: + excludes: + - G110 + - G115 + - G204 + - G306 lll: line-length: 150 diff --git a/cmd/gitops-server/cmd/cmd.go b/cmd/gitops-server/cmd/cmd.go index 12e2a3fa47..500a00af5e 100644 --- a/cmd/gitops-server/cmd/cmd.go +++ b/cmd/gitops-server/cmd/cmd.go @@ -293,8 +293,9 @@ func runCmd(cmd *cobra.Command, args []string) error { addr := net.JoinHostPort(options.Host, options.Port) srv := &http.Server{ - Addr: addr, - Handler: handler, + Addr: addr, + Handler: handler, + ReadHeaderTimeout: 5 * time.Second, } go func() { @@ -318,8 +319,9 @@ func runCmd(cmd *cobra.Command, args []string) error { metricsMux.Handle("/metrics", promhttp.HandlerFor(gatherers, promhttp.HandlerOpts{})) metricsServer = &http.Server{ - Addr: options.MetricsAddress, - Handler: metricsMux, + Addr: options.MetricsAddress, + Handler: metricsMux, + ReadHeaderTimeout: 5 * time.Second, } go func() { @@ -375,6 +377,7 @@ func listenAndServe(log logr.Logger, srv *http.Server, options Options) error { srv.TLSConfig = &tls.Config{ ClientCAs: caCertPool, ClientAuth: tls.RequireAndVerifyClientCert, + MinVersion: tls.VersionTLS12, } } else { log.Info("Using TLS", "cert_file", options.TLSCertFile, "key_file", options.TLSKeyFile) diff --git a/cmd/gitops/root/cmd.go b/cmd/gitops/root/cmd.go index 8ab785a8df..367e4b94a5 100644 --- a/cmd/gitops/root/cmd.go +++ b/cmd/gitops/root/cmd.go @@ -3,9 +3,9 @@ package root import ( "fmt" "log" + "math/rand/v2" "os" "strings" - "time" "github.com/manifoldco/promptui" "github.com/spf13/cobra" @@ -121,10 +121,8 @@ func RootCmd() *cobra.Command { enableAnalytics = true } - seed := time.Now().UnixNano() - gitopsConfig = &config.GitopsCLIConfig{ - UserID: config.GenerateUserID(10, seed), + UserID: config.GenerateUserID(10, rand.Uint64()), // #nosec G404 Analytics: enableAnalytics, } diff --git a/cmd/gitops/set/config/cmd.go b/cmd/gitops/set/config/cmd.go index 1efac6be9f..7c26d436bb 100644 --- a/cmd/gitops/set/config/cmd.go +++ b/cmd/gitops/set/config/cmd.go @@ -2,10 +2,10 @@ package config import ( "fmt" + "math/rand/v2" "os" "strconv" "strings" - "time" "github.com/spf13/cobra" @@ -77,9 +77,7 @@ func setConfigCommandRunE(opts *cfg.Options) func(*cobra.Command, []string) erro gitopsConfig.Analytics = analyticsValue if gitopsConfig.UserID == "" { - seed := time.Now().UnixNano() - - gitopsConfig.UserID = config.GenerateUserID(10, seed) + gitopsConfig.UserID = config.GenerateUserID(10, rand.Uint64()) // #nosec G404 } log.Actionf("Saving GitOps CLI config ...") diff --git a/core/server/inventory.go b/core/server/inventory.go index b527a80401..ac4d106553 100644 --- a/core/server/inventory.go +++ b/core/server/inventory.go @@ -479,7 +479,7 @@ func parseInventoryFromUnstructured(obj *unstructured.Unstructured) ([]*unstruct return objects, nil } -const helmSecretNameFmt = "sh.helm.release.v1.%s.v%v" +const helmSecretNameFmt = "sh.helm.release.v1.%s.v%v" // #nosec G101 func secretNameFromHelmRelease(helmRelease *helmv2.HelmRelease) *client.ObjectKey { if latest := helmRelease.Status.History.Latest(); latest != nil { diff --git a/pkg/analytics/analytics.go b/pkg/analytics/analytics.go index ce5696197f..632a0c2eff 100644 --- a/pkg/analytics/analytics.go +++ b/pkg/analytics/analytics.go @@ -26,7 +26,7 @@ const ( app = "cli" analyticsType = "track" trackEventURL = "https://app.pendo.io/data/track" - trackEventSecret = "bf6ab33e-cd70-46e7-4b77-279f54cac447" + trackEventSecret = "bf6ab33e-cd70-46e7-4b77-279f54cac447" // #nosec G101 ) type analyticsRequestBody struct { diff --git a/pkg/config/config.go b/pkg/config/config.go index 24867bbd3a..d81853d495 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -6,7 +6,7 @@ import ( "fmt" "io" "io/fs" - "math/rand" + "math/rand/v2" "os" "path/filepath" ) @@ -188,12 +188,12 @@ func parseConfig(data []byte, config *GitopsCLIConfig) error { } // GenerateUserID generates a string of specified length made of random characters and encodes it in base64 format -func GenerateUserID(numChars int, seed int64) string { - srand := rand.New(rand.NewSource(seed)) +func GenerateUserID(numChars int, seed uint64) string { + srand := rand.New(rand.NewPCG(seed, 0)) // #nosec G404 b := make([]byte, numChars) for i := range b { - b[i] = letters[srand.Intn(len(letters))] + b[i] = letters[srand.IntN(len(letters))] } return string(b) diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 940b4a39a8..6d2d1f6eeb 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -25,6 +25,6 @@ var _ = Describe("GenerateUserID", func() { It("generates user ID", func() { userID := GenerateUserID(10, 1024) - Expect(userID).To(Equal("2Q2MsgBDSV")) + Expect(userID).To(Equal("ULhi8C5Ti1")) }) }) diff --git a/pkg/http/server.go b/pkg/http/server.go index 3072d7d783..d94ce9f036 100644 --- a/pkg/http/server.go +++ b/pkg/http/server.go @@ -8,6 +8,7 @@ import ( "net" "net/http" "sync" + "time" ) // MultiServer lets you create and run an HTTP server that serves over both, HTTP and HTTPS. It is a convenience wrapper around net/http and crypto/tls. @@ -59,7 +60,7 @@ func createTLSListener(port int, certFile, keyFile string) (net.Listener, error) return nil, fmt.Errorf("unable to load TLS key pair: %w", err) } - listener, err := tls.Listen("tcp", fmt.Sprintf(":%d", port), &tls.Config{Certificates: []tls.Certificate{cert}}) + listener, err := tls.Listen("tcp", fmt.Sprintf(":%d", port), &tls.Config{Certificates: []tls.Certificate{cert}, MinVersion: tls.VersionTLS12}) if err != nil { return nil, fmt.Errorf("unable to start TLS listener: %w", err) } @@ -69,8 +70,9 @@ func createTLSListener(port int, certFile, keyFile string) (net.Listener, error) func startServer(ctx context.Context, hndlr http.Handler, listener net.Listener, logger *log.Logger) { srv := http.Server{ - Addr: listener.Addr().String(), - Handler: hndlr, + Addr: listener.Addr().String(), + Handler: hndlr, + ReadHeaderTimeout: 5 * time.Second, } logger.Printf("https://%s", srv.Addr) diff --git a/pkg/http/server_test.go b/pkg/http/server_test.go index ff3996b8d5..c5f7d7368f 100644 --- a/pkg/http/server_test.go +++ b/pkg/http/server_test.go @@ -7,7 +7,7 @@ import ( "fmt" "io" "log" - "math/rand" + "math/rand/v2" "net/http" "os" "testing" @@ -43,11 +43,11 @@ func TestMultiServerWithoutTLSConfigFailsToStart(t *testing.T) { func TestMultiServerServesOverBothProtocols(t *testing.T) { g := NewGomegaWithT(t) - httpPort := rand.Intn(49151-1024) + 1024 - httpsPort := rand.Intn(49151-1024) + 1024 + httpPort := rand.N(49151-1024) + 1024 // #nosec G404 + httpsPort := rand.N(49151-1024) + 1024 // #nosec G404 for httpPort == httpsPort { - httpsPort = rand.Intn(49151-1024) + 1024 + httpsPort = rand.N(49151-1024) + 1024 // #nosec G404 } srv := wegohttp.MultiServer{ @@ -93,7 +93,8 @@ func TestMultiServerServesOverBothProtocols(t *testing.T) { tr := &http.Transport{ TLSClientConfig: &tls.Config{ - RootCAs: rootCAs, + RootCAs: rootCAs, + MinVersion: tls.VersionTLS12, }, } c := http.Client{ diff --git a/pkg/kube/kube_suite_test.go b/pkg/kube/kube_suite_test.go index 8256d813ae..32f1ad66b8 100644 --- a/pkg/kube/kube_suite_test.go +++ b/pkg/kube/kube_suite_test.go @@ -1,9 +1,7 @@ package kube_test import ( - "math/rand" "testing" - "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -39,7 +37,3 @@ var _ = BeforeSuite(func() { var _ = AfterSuite(func() { cleanupK8s() }) - -func init() { - rand.New(rand.NewSource(time.Now().UnixNano())) -} diff --git a/pkg/names/names.go b/pkg/names/names.go index 660f1c2730..fdafc7dc6c 100644 --- a/pkg/names/names.go +++ b/pkg/names/names.go @@ -1,7 +1,7 @@ package names import ( - "crypto/md5" + "crypto/sha256" "fmt" "strings" @@ -43,7 +43,7 @@ func hashNameIfTooLong(name string) string { return name } - return fmt.Sprintf("wego-%x", md5.Sum([]byte(name))) + return fmt.Sprintf("wego-%x", sha256.Sum224([]byte(name))) } func ApplicationNameTooLong(name string) bool { diff --git a/pkg/oidc/check/flow_test.go b/pkg/oidc/check/flow_test.go index 904f71d913..81b4a67f99 100644 --- a/pkg/oidc/check/flow_test.go +++ b/pkg/oidc/check/flow_test.go @@ -38,7 +38,7 @@ func (tp TestProvider) genToken() string { } func (tp *TestProvider) Start() error { - listener, err := net.Listen("tcp", ":8765") + listener, err := net.Listen("tcp", "127.0.0.1:8765") if err != nil { return fmt.Errorf("failed starting listener: %w", err) } @@ -46,7 +46,8 @@ func (tp *TestProvider) Start() error { tp.URL = fmt.Sprintf("http://%s", listener.Addr().String()) mux := http.ServeMux{} tp.srv = &http.Server{ - Handler: &mux, + Handler: &mux, + ReadHeaderTimeout: 5 * time.Second, } mux.HandleFunc("/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) { @@ -160,7 +161,7 @@ func TestGetClaimsWithSecret(t *testing.T) { SecretName: "test-oidc", SecretNamespace: "flux-system", OpenURL: func(u string) error { - http.Get(u) + http.Get(u) // #nosec: G107 return nil }, InsecureSkipSignatureCheck: true, @@ -311,7 +312,7 @@ func TestGetClaimsWithoutSecret(t *testing.T) { if tt.opts.OpenURL == nil { tt.opts.OpenURL = func(u string) error { - http.Get(u) + http.Get(u) // #nosec: G107 return nil } } diff --git a/pkg/oidc/check/server.go b/pkg/oidc/check/server.go index 0a5ccfd6ef..9be43a6b8c 100644 --- a/pkg/oidc/check/server.go +++ b/pkg/oidc/check/server.go @@ -27,7 +27,8 @@ var errorHTML string func retrieveIDToken(log logger.Logger, oauth2Config oauth2.Config, verifier *oidc.IDTokenVerifier) (*oidc.IDToken, error) { mux := http.ServeMux{} srv := http.Server{ - Handler: &mux, + Handler: &mux, + ReadHeaderTimeout: 5 * time.Second, } var idToken *oidc.IDToken var handleErr error @@ -70,7 +71,7 @@ func retrieveIDToken(log logger.Logger, oauth2Config oauth2.Config, verifier *oi fmt.Fprint(w, successHTML) }) - listener, err := net.Listen("tcp", ":9876") + listener, err := net.Listen("tcp", ":9876") // #nosec G102 if err != nil { return nil, fmt.Errorf("failed starting listener: %w", err) } diff --git a/pkg/s3/auth_middleware_test.go b/pkg/s3/auth_middleware_test.go index d2b3a996f0..d349f91d17 100644 --- a/pkg/s3/auth_middleware_test.go +++ b/pkg/s3/auth_middleware_test.go @@ -4,11 +4,10 @@ import ( "bytes" "fmt" "io" - "math/rand" + "math/rand/v2" "net/http" "net/http/httptest" "testing" - "time" "github.com/minio/minio-go/v7/pkg/signer" . "github.com/onsi/gomega" @@ -19,11 +18,9 @@ func generateRandomBody(method string) io.Reader { return nil } - srand := rand.New(rand.NewSource(time.Now().UnixNano())) - - size := srand.Intn(2000) + 2000 + size := rand.N(2000) + 2000 // #nosec G404 buf := make([]byte, size) - srand.Read(buf) + _, _ = rand.NewChaCha8([32]byte{}).Read(buf) return bytes.NewReader(buf) } diff --git a/pkg/s3/secret_test.go b/pkg/s3/secret_test.go index 972b9e5578..bc51367db8 100644 --- a/pkg/s3/secret_test.go +++ b/pkg/s3/secret_test.go @@ -4,13 +4,13 @@ import ( "fmt" "io" "math/big" - "math/rand" + "math/rand/v2" "testing" . "github.com/onsi/gomega" ) -func deterministicRandInt(seed int64, err error) RandIntFunc { +func deterministicRandInt(seed uint64, err error) RandIntFunc { var srand *rand.Rand return func(_ io.Reader, max *big.Int) (*big.Int, error) { @@ -19,10 +19,10 @@ func deterministicRandInt(seed int64, err error) RandIntFunc { } if srand == nil { - srand = rand.New(rand.NewSource(seed)) + srand = rand.New(rand.NewPCG(seed, 0)) // #nosec G404 } - return big.NewInt(int64(srand.Intn(int(max.Int64())))), nil + return big.NewInt(srand.Int64N(max.Int64())), nil // #nosec G404 } } @@ -38,7 +38,7 @@ func TestGenerators(t *testing.T) { name: "GenerateAccessKey generates a deterministic access key", generator: GenerateAccessKey, randIntFunc: deterministicRandInt(100, nil), - expected: "AKIA5UQA4UZJM3", + expected: "AKIATBK3988IAG", expectedErr: false, }, { @@ -52,7 +52,7 @@ func TestGenerators(t *testing.T) { name: "GenerateSecretKey generates a deterministic secret key", generator: GenerateSecretKey, randIntFunc: deterministicRandInt(512, nil), - expected: "Fg5n9W6CwTfnMu4FzEk8xuTomwk2OpFe0yLcLMAL", + expected: "0aEEdyKByGEXsQUh1af86o6HON4Ig468I6DhJH1C", expectedErr: false, }, { diff --git a/pkg/server/auth/auth.go b/pkg/server/auth/auth.go index 9a4fce36cb..adcc6fd3c8 100644 --- a/pkg/server/auth/auth.go +++ b/pkg/server/auth/auth.go @@ -2,8 +2,8 @@ package auth import ( "context" - "crypto/md5" "crypto/rand" + "crypto/sha256" "encoding/base64" "encoding/hex" "fmt" @@ -106,7 +106,7 @@ func (p *UserPrincipal) String() string { // Hash returns a unique string using user id,token and groups. func (p *UserPrincipal) Hash() string { - hash := md5.Sum([]byte(fmt.Sprintf("%s/%s/%v", p.ID, p.Token(), p.Groups))) + hash := sha256.Sum224([]byte(fmt.Sprintf("%s/%s/%v", p.ID, p.Token(), p.Groups))) return hex.EncodeToString(hash[:]) } diff --git a/pkg/server/auth/server.go b/pkg/server/auth/server.go index 11b30dc2e7..bfe9229263 100644 --- a/pkg/server/auth/server.go +++ b/pkg/server/auth/server.go @@ -24,12 +24,12 @@ import ( const ( LoginOIDC string = "oidc" LoginUsername string = "username" - ClusterUserAuthSecretName string = "cluster-user-auth" - DefaultOIDCAuthSecretName string = "oidc-auth" + ClusterUserAuthSecretName string = "cluster-user-auth" // #nosec G101 + DefaultOIDCAuthSecretName string = "oidc-auth" // #nosec G101 FeatureFlagClusterUser string = "CLUSTER_USER_AUTH" FeatureFlagAnonymousAuth string = "ANONYMOUS_AUTH" FeatureFlagOIDCAuth string = "OIDC_AUTH" - FeatureFlagOIDCPassthrough string = "WEAVE_GITOPS_FEATURE_OIDC_AUTH_PASSTHROUGH" + FeatureFlagOIDCPassthrough string = "WEAVE_GITOPS_FEATURE_OIDC_AUTH_PASSTHROUGH" // #nosec G101 // ClaimUsername is the default claim for getting the user from OIDC for // auth diff --git a/pkg/services/auth/github.go b/pkg/services/auth/github.go index a18592d001..4d3d98286a 100644 --- a/pkg/services/auth/github.go +++ b/pkg/services/auth/github.go @@ -118,7 +118,7 @@ var ( ) const ( - accessTokenURL = "https://github.com/login/oauth/access_token?%s" + accessTokenURL = "https://github.com/login/oauth/access_token?%s" // #nosec G101 githubRequiredGrantType = "urn:ietf:params:oauth:grant-type:device_code" ) diff --git a/pkg/services/auth/internal/gitlab.go b/pkg/services/auth/internal/gitlab.go index 410647b6be..b44e91f298 100644 --- a/pkg/services/auth/internal/gitlab.go +++ b/pkg/services/auth/internal/gitlab.go @@ -12,7 +12,7 @@ const ( gitlabHost = "gitlab.com" // Default values that can be used for OAuth with the `wego-dev` GitLab Application gitlabClientID = "451df5d954a3ebb371bba5e6b7d1468ead1a0ee6d88b0791b001566b7bbc10cd" - gitlabClientSecret = "b402c7601b71904fffec85d3cc8aa7e953405680aa9b1fc4fb8603e9bb7e208a" + gitlabClientSecret = "b402c7601b71904fffec85d3cc8aa7e953405680aa9b1fc4fb8603e9bb7e208a" // #nosec G101 GitlabVerifierMin = 43 GitlabVerifierMax = 128 GitlabRedirectURICLI = "http://127.0.0.1:9999/oauth/gitlab/callback" diff --git a/pkg/services/auth/types/token_test.go b/pkg/services/auth/types/token_test.go index 86799567c7..6a015c594d 100644 --- a/pkg/services/auth/types/token_test.go +++ b/pkg/services/auth/types/token_test.go @@ -13,10 +13,10 @@ var _ = Describe("TokenResponseState", func() { var token *TokenResponseState var tokenResponse internal.GitlabTokenResponse - accessToken := "kEq6PWZ8x37CNNmk" + accessToken := "kEq6PWZ8x37CNNmk" // #nosec G101 tokenType := "test-token-type" var seconds int64 = 600 - refreshToken := "H2q4xABSMT" + refreshToken := "H2q4xABSMT" // #nosec G101 var createdAt int64 = 32425434 _ = BeforeEach(func() { diff --git a/pkg/utils/string.go b/pkg/utils/string.go index be50e77ba5..7a40993d22 100644 --- a/pkg/utils/string.go +++ b/pkg/utils/string.go @@ -4,8 +4,7 @@ import ( "crypto/rand" "fmt" "math/big" - mrand "math/rand" - "time" + mrand "math/rand/v2" ) const ( @@ -16,8 +15,6 @@ const ( // The length can also vary by using the min and max parameters. To have a consistent length // such as 11, you would pass (11, 12) for the min and max respectively func GenerateRandomString(minLen, maxLen int) (string, error) { - mrand.New(mrand.NewSource(time.Now().UnixNano())) - length := randInt(minLen, maxLen) value := make([]byte, length) @@ -34,5 +31,5 @@ func GenerateRandomString(minLen, maxLen int) (string, error) { } func randInt(minVal, maxVal int) int { - return minVal + mrand.Intn(maxVal-minVal) + return minVal + mrand.N(maxVal-minVal) // #nosec G404 }