diff --git a/.golangci.yaml b/.golangci.yaml index 10cff8c61..40e33f14b 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,6 +1,9 @@ # https://golangci-lint.run/usage/configuration/ version: "2" +issues: + max-issues-per-linter: 200 + max-same-issues: 200 linters: default: none enable: diff --git a/hack/lib/lint-version.txt b/hack/lib/lint-version.txt index c8e38b614..7cd5929f9 100644 --- a/hack/lib/lint-version.txt +++ b/hack/lib/lint-version.txt @@ -1 +1 @@ -2.9.0 +2.11.4 diff --git a/internal/concierge/impersonator/impersonator_test.go b/internal/concierge/impersonator/impersonator_test.go index 9e476069b..ff56b09a6 100644 --- a/internal/concierge/impersonator/impersonator_test.go +++ b/internal/concierge/impersonator/impersonator_test.go @@ -1626,6 +1626,7 @@ func TestImpersonatorHTTPHandler(t *testing.T) { wantHTTPBody: `{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Internal error occurred: unimplemented functionality - unable to act as current user","reason":"InternalError","details":{"causes":[{"message":"unimplemented functionality - unable to act as current user"}]},"code":500}` + "\n", wantHTTPStatus: http.StatusInternalServerError, }, + //nolint:gosec // no real credentials here { name: "authenticated user with UID and bearer token results in error", requestHeaders: map[string][]string{ diff --git a/internal/config/concierge/config_test.go b/internal/config/concierge/config_test.go index 319608885..0469ce435 100644 --- a/internal/config/concierge/config_test.go +++ b/internal/config/concierge/config_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package concierge @@ -103,6 +103,7 @@ func TestFromPath(t *testing.T) { "ValidatingAdmissionWebhook", }, ImpersonationProxyServerPort: ptr.To[int64](4242), + //nolint:gosec // no credentials here NamesConfig: NamesConfigSpec{ ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate", CredentialIssuer: "pinniped-config", @@ -215,6 +216,7 @@ func TestFromPath(t *testing.T) { "ValidatingAdmissionWebhook", }, ImpersonationProxyServerPort: ptr.To[int64](4242), + //nolint:gosec // no credentials here NamesConfig: NamesConfigSpec{ ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate", CredentialIssuer: "pinniped-config", @@ -322,6 +324,7 @@ func TestFromPath(t *testing.T) { RenewBeforeSeconds: ptr.To[int64](60 * 60 * 24 * 30 * 9), // about 9 months }, }, + //nolint:gosec // no credentials here NamesConfig: NamesConfigSpec{ ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate", CredentialIssuer: "pinniped-config", diff --git a/internal/controller/apicerts/apiservice_updater_test.go b/internal/controller/apicerts/apiservice_updater_test.go index 448e9f5cd..fc1b43810 100644 --- a/internal/controller/apicerts/apiservice_updater_test.go +++ b/internal/controller/apicerts/apiservice_updater_test.go @@ -146,6 +146,7 @@ func TestAPIServiceUpdaterControllerSync(t *testing.T) { it.Before(func() { r = require.New(t) + //nolint:gosec // cancelContextCancelFunc is called in the After() cancelContext, cancelContextCancelFunc = context.WithCancel(context.Background()) kubeInformerClient = kubefake.NewClientset() diff --git a/internal/controller/apicerts/certs_manager_test.go b/internal/controller/apicerts/certs_manager_test.go index e87f019ed..f92783bcd 100644 --- a/internal/controller/apicerts/certs_manager_test.go +++ b/internal/controller/apicerts/certs_manager_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package apicerts @@ -168,6 +168,7 @@ func TestManagerControllerSync(t *testing.T) { it.Before(func() { r = require.New(t) + //nolint:gosec // cancelContextCancelFunc is called in the After() cancelContext, cancelContextCancelFunc = context.WithCancel(context.Background()) kubeInformerClient = kubefake.NewClientset() diff --git a/internal/controller/apicerts/certs_observer_test.go b/internal/controller/apicerts/certs_observer_test.go index f9a501892..6d2cdf813 100644 --- a/internal/controller/apicerts/certs_observer_test.go +++ b/internal/controller/apicerts/certs_observer_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package apicerts @@ -142,6 +142,7 @@ func TestObserverControllerSync(t *testing.T) { it.Before(func() { r = require.New(t) + //nolint:gosec // cancelContextCancelFunc is called in the After() cancelContext, cancelContextCancelFunc = context.WithCancel(context.Background()) kubeInformerClient = kubefake.NewClientset() diff --git a/internal/controller/impersonatorconfig/impersonator_config_test.go b/internal/controller/impersonatorconfig/impersonator_config_test.go index e598ebc1a..f671f1c2b 100644 --- a/internal/controller/impersonatorconfig/impersonator_config_test.go +++ b/internal/controller/impersonatorconfig/impersonator_config_test.go @@ -342,6 +342,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) { return nil, nil // no cached TLS certs }, ClientAuth: tls.RequestClientCert, + //nolint:gosec // not worried about session resumption in this test VerifyPeerCertificate: func(rawCerts [][]byte, _ [][]*x509.Certificate) error { // Docs say that this will always be called in tls.RequestClientCert mode // and that the second parameter will always be nil in that case. @@ -486,7 +487,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) { rootCAs := x509.NewCertPool() rootCAs.AppendCertsFromPEM(caCrt) tr = &http.Transport{ - TLSClientConfig: &tls.Config{ //nolint:gosec // not concerned with TLS MinVersion here + TLSClientConfig: &tls.Config{ // Server's TLS serving cert CA RootCAs: rootCAs, // Client cert which is supposed to work against the server's dynamic CAContentProvider @@ -1127,6 +1128,8 @@ func TestImpersonatorConfigControllerSync(t *testing.T) { it.Before(func() { r = require.New(t) queue = &testQueue{} + + //nolint:gosec // cancelContextCancelFunc is called in the After() cancelContext, cancelContextCancelFunc = context.WithCancel(context.Background()) //nolint:staticcheck // our codegen does not yet generate a NewClientset() function @@ -1986,6 +1989,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) { r.Len(kubeAPIClient.Actions(), 3) requireNodesListed(kubeAPIClient.Actions()[0]) lbService := requireLoadBalancerWasCreated(kubeAPIClient.Actions()[1]) + //nolint:gosec // no credentials here r.Equal(lbService.Annotations, map[string]string{ "some-annotation-key": "some-annotation-value", "credentialissuer.pinniped.dev/annotation-keys": `["some-annotation-key"]`, @@ -2783,6 +2787,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) { r.Len(kubeAPIClient.Actions(), 4) requireNodesListed(kubeAPIClient.Actions()[0]) lbService := requireLoadBalancerWasCreated(kubeAPIClient.Actions()[1]) + //nolint:gosec // no credentials here r.Equal(map[string]string{"credentialissuer.pinniped.dev/label-keys": `["app","other-key"]`}, lbService.Annotations) ca := requireCASecretWasCreated(kubeAPIClient.Actions()[2]) requireTLSSecretWasCreated(kubeAPIClient.Actions()[3], ca) @@ -2823,6 +2828,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) { wantLabels := maps.Clone(labels) wantLabels["my-label-key"] = "my-label-from-unrelated-controller-val" r.Equal(wantLabels, lbService.Labels) + //nolint:gosec // no credentials here r.Equal(map[string]string{ // Now the CredentialIssuer annotations should be merged on the load balancer. // In the unlikely case where keys conflict, the CredentialIssuer value overwrites the other value. @@ -2864,6 +2870,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) { r.Len(kubeAPIClient.Actions(), 4) requireNodesListed(kubeAPIClient.Actions()[0]) clusterIPService := requireClusterIPWasCreated(kubeAPIClient.Actions()[1]) + //nolint:gosec // no credentials here r.Equal(map[string]string{"credentialissuer.pinniped.dev/label-keys": `["app","other-key"]`}, clusterIPService.Annotations) ca := requireCASecretWasCreated(kubeAPIClient.Actions()[2]) requireTLSSecretWasCreated(kubeAPIClient.Actions()[3], ca) @@ -2904,6 +2911,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) { wantLabels := maps.Clone(labels) wantLabels["my-label-key"] = "my-label-from-unrelated-controller-val" r.Equal(wantLabels, clusterIPService.Labels) + //nolint:gosec // no credentials here r.Equal(map[string]string{ // Now the CredentialIssuer annotations should be merged on the load balancer. // In the unlikely case where keys conflict, the CredentialIssuer value overwrites the other value. @@ -2950,6 +2958,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) { r.Len(kubeAPIClient.Actions(), 4) requireNodesListed(kubeAPIClient.Actions()[0]) lbService := requireLoadBalancerWasCreated(kubeAPIClient.Actions()[1]) + //nolint:gosec // no credentials here r.Equal(map[string]string{ "my-initial-annotation1-key": "my-initial-annotation1-val", "my-initial-annotation2-key": "my-initial-annotation2-val", @@ -2994,6 +3003,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) { r.Len(kubeAPIClient.Actions(), 5) // one more item to update the loadbalancer lbService = requireLoadBalancerWasUpdated(kubeAPIClient.Actions()[4]) r.Equal(labels, lbService.Labels) + //nolint:gosec // no credentials here r.Equal(map[string]string{ // Now the CredentialIssuer annotations should be merged on the load balancer. // Since the user removed the "my-initial-annotation2-key" key from the CredentialIssuer spec, @@ -3025,6 +3035,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) { r.Len(kubeAPIClient.Actions(), 6) // one more item to update the loadbalancer lbService = requireLoadBalancerWasUpdated(kubeAPIClient.Actions()[5]) r.Equal(labels, lbService.Labels) + //nolint:gosec // no credentials here r.Equal(map[string]string{ // Since the user removed all annotations from the CredentialIssuer spec, // they should all be removed from the Service, along with the special bookkeeping annotation too. @@ -3076,6 +3087,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) { requireNodesListed(kubeAPIClient.Actions()[0]) lbService := requireLoadBalancerWasUpdated(kubeAPIClient.Actions()[1]) r.Equal(labels, lbService.Labels) + //nolint:gosec // no credentials here r.Equal(map[string]string{ "some-annotation": "annotation-value", "credentialissuer.pinniped.dev/annotation-keys": `["some-annotation"]`, @@ -3115,6 +3127,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) { r.Len(kubeAPIClient.Actions(), 4) requireNodesListed(kubeAPIClient.Actions()[0]) lbService := requireLoadBalancerWasCreated(kubeAPIClient.Actions()[1]) + //nolint:gosec // no credentials here r.Equal(map[string]string{"credentialissuer.pinniped.dev/label-keys": `["app","other-key"]`}, lbService.Annotations) r.Equal("", lbService.Spec.LoadBalancerIP) ca := requireCASecretWasCreated(kubeAPIClient.Actions()[2]) diff --git a/internal/controller/supervisorconfig/githubupstreamwatcher/github_upstream_watcher_test.go b/internal/controller/supervisorconfig/githubupstreamwatcher/github_upstream_watcher_test.go index 228858c6a..0923e4082 100644 --- a/internal/controller/supervisorconfig/githubupstreamwatcher/github_upstream_watcher_test.go +++ b/internal/controller/supervisorconfig/githubupstreamwatcher/github_upstream_watcher_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package githubupstreamwatcher @@ -592,6 +592,7 @@ func TestController(t *testing.T) { OAuth2Config: &oauth2.Config{ ClientID: "some-client-id", ClientSecret: "some-client-secret", + //nolint:gosec // no credentials here Endpoint: oauth2.Endpoint{ AuthURL: "https://github.com/login/oauth/authorize", DeviceAuthURL: "", // not used @@ -667,6 +668,7 @@ func TestController(t *testing.T) { OAuth2Config: &oauth2.Config{ ClientID: "some-client-id", ClientSecret: "some-client-secret", + //nolint:gosec // no credentials here Endpoint: oauth2.Endpoint{ AuthURL: "https://github.com/login/oauth/authorize", DeviceAuthURL: "", // not used @@ -742,6 +744,7 @@ func TestController(t *testing.T) { OAuth2Config: &oauth2.Config{ ClientID: "some-client-id", ClientSecret: "some-client-secret", + //nolint:gosec // no credentials here Endpoint: oauth2.Endpoint{ AuthURL: "https://github.com/login/oauth/authorize", DeviceAuthURL: "", // not used @@ -817,6 +820,7 @@ func TestController(t *testing.T) { OAuth2Config: &oauth2.Config{ ClientID: "some-client-id", ClientSecret: "some-client-secret", + //nolint:gosec // no credentials here Endpoint: oauth2.Endpoint{ AuthURL: "https://github.com/login/oauth/authorize", DeviceAuthURL: "", // not used @@ -892,6 +896,7 @@ func TestController(t *testing.T) { OAuth2Config: &oauth2.Config{ ClientID: "some-client-id", ClientSecret: "some-client-secret", + //nolint:gosec // no credentials here Endpoint: oauth2.Endpoint{ AuthURL: "https://github.com/login/oauth/authorize", DeviceAuthURL: "", // not used diff --git a/internal/controller/supervisorconfig/jwks_observer_test.go b/internal/controller/supervisorconfig/jwks_observer_test.go index a707bd731..7e2bc3b9a 100644 --- a/internal/controller/supervisorconfig/jwks_observer_test.go +++ b/internal/controller/supervisorconfig/jwks_observer_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package supervisorconfig @@ -165,6 +165,7 @@ func TestJWKSObserverControllerSync(t *testing.T) { it.Before(func() { r = require.New(t) + //nolint:gosec // cancelContextCancelFunc is called in the After() cancelContext, cancelContextCancelFunc = context.WithCancel(context.Background()) kubeInformerClient = kubefake.NewClientset() diff --git a/internal/controller/supervisorconfig/oidcupstreamwatcher/oidc_upstream_watcher_test.go b/internal/controller/supervisorconfig/oidcupstreamwatcher/oidc_upstream_watcher_test.go index 7cae9fead..71b85c846 100644 --- a/internal/controller/supervisorconfig/oidcupstreamwatcher/oidc_upstream_watcher_test.go +++ b/internal/controller/supervisorconfig/oidcupstreamwatcher/oidc_upstream_watcher_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package oidcupstreamwatcher @@ -230,8 +230,8 @@ func TestOIDCUpstreamWatcherControllerSync(t *testing.T) { testNamespace = "test-namespace" testName = "test-name" testSecretName = "test-client-secret" - testAdditionalScopes = []string{"scope1", "scope2", "scope3"} - testExpectedScopes = []string{"openid", "scope1", "scope2", "scope3"} + testAdditionalScopes = []string{"scope1", "scope2", "scope3"} //nolint:prealloc + testExpectedScopes = []string{"openid", "scope1", "scope2", "scope3"} //nolint:prealloc testDefaultExpectedScopes = []string{"openid", "offline_access", "email", "profile"} testAdditionalParams = []idpv1alpha1.Parameter{{Name: "prompt", Value: "consent"}, {Name: "foo", Value: "bar"}} testExpectedAdditionalParams = map[string]string{"prompt": "consent", "foo": "bar"} @@ -1919,6 +1919,7 @@ func newTestIssuer(t *testing.T) (string, string) { // At the root of the server, serve an issuer with a valid discovery response. mux.HandleFunc("/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", "application/json") + //nolint:gosec // no credentials here _ = json.NewEncoder(w).Encode(&providerJSON{ Issuer: server.URL, AuthURL: "https://example.com/authorize", @@ -1931,6 +1932,7 @@ func newTestIssuer(t *testing.T) (string, string) { // At "/valid-without-revocation", serve an issuer with a valid discovery response which does not have a revocation endpoint. mux.HandleFunc("/valid-without-revocation/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", "application/json") + //nolint:gosec // no credentials here _ = json.NewEncoder(w).Encode(&providerJSON{ Issuer: server.URL + "/valid-without-revocation", AuthURL: "https://example.com/authorize", @@ -1943,6 +1945,7 @@ func newTestIssuer(t *testing.T) (string, string) { // At "/valid-without-userinfo", serve an issuer with a valid discovery response which does not have a userinfo endpoint. mux.HandleFunc("/valid-without-userinfo/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", "application/json") + //nolint:gosec // no credentials here _ = json.NewEncoder(w).Encode(&providerJSON{ Issuer: server.URL + "/valid-without-userinfo", AuthURL: "https://example.com/authorize", @@ -1955,6 +1958,7 @@ func newTestIssuer(t *testing.T) (string, string) { // At "/invalid", serve an issuer that returns an invalid authorization URL (not parseable). mux.HandleFunc("/invalid/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", "application/json") + //nolint:gosec // no credentials here _ = json.NewEncoder(w).Encode(&providerJSON{ Issuer: server.URL + "/invalid", AuthURL: "%", @@ -1965,6 +1969,7 @@ func newTestIssuer(t *testing.T) (string, string) { // At "/invalid-revocation-url", serve an issuer that returns an invalid revocation URL (not parseable). mux.HandleFunc("/invalid-revocation-url/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", "application/json") + //nolint:gosec // no credentials here _ = json.NewEncoder(w).Encode(&providerJSON{ Issuer: server.URL + "/invalid-revocation-url", AuthURL: "https://example.com/authorize", @@ -1976,6 +1981,7 @@ func newTestIssuer(t *testing.T) (string, string) { // At "/insecure", serve an issuer that returns an insecure authorization URL (not https://). mux.HandleFunc("/insecure/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", "application/json") + //nolint:gosec // no credentials here _ = json.NewEncoder(w).Encode(&providerJSON{ Issuer: server.URL + "/insecure", AuthURL: "http://example.com/authorize", @@ -1986,6 +1992,7 @@ func newTestIssuer(t *testing.T) (string, string) { // At "/insecure-revocation-url", serve an issuer that returns an insecure revocation URL (not https://). mux.HandleFunc("/insecure-revocation-url/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", "application/json") + //nolint:gosec // no credentials here _ = json.NewEncoder(w).Encode(&providerJSON{ Issuer: server.URL + "/insecure-revocation-url", AuthURL: "https://example.com/authorize", @@ -1997,6 +2004,7 @@ func newTestIssuer(t *testing.T) (string, string) { // At "/insecure-token-url", serve an issuer that returns an insecure token URL (not https://). mux.HandleFunc("/insecure-token-url/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", "application/json") + //nolint:gosec // no credentials here _ = json.NewEncoder(w).Encode(&providerJSON{ Issuer: server.URL + "/insecure-token-url", AuthURL: "https://example.com/authorize", @@ -2019,6 +2027,7 @@ func newTestIssuer(t *testing.T) (string, string) { // At "/missing-auth-url", serve an issuer that returns no auth URL, which is required by the spec. mux.HandleFunc("/missing-auth-url/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", "application/json") + //nolint:gosec // no credentials here _ = json.NewEncoder(w).Encode(&providerJSON{ Issuer: server.URL + "/missing-auth-url", RevocationURL: "https://example.com/revoke", @@ -2034,6 +2043,7 @@ func newTestIssuer(t *testing.T) (string, string) { // valid case in=/ out=/ mux.HandleFunc("/ends-with-slash/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", "application/json") + //nolint:gosec // no credentials here _ = json.NewEncoder(w).Encode(&providerJSON{ Issuer: server.URL + "/ends-with-slash/", AuthURL: "https://example.com/authorize", diff --git a/internal/controller/supervisorconfig/tls_cert_observer_test.go b/internal/controller/supervisorconfig/tls_cert_observer_test.go index e8f7d1eb7..697cfb830 100644 --- a/internal/controller/supervisorconfig/tls_cert_observer_test.go +++ b/internal/controller/supervisorconfig/tls_cert_observer_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package supervisorconfig @@ -178,6 +178,7 @@ func TestTLSCertObserverControllerSync(t *testing.T) { it.Before(func() { r = require.New(t) + //nolint:gosec // cancelContextCancelFunc is called in the After() cancelContext, cancelContextCancelFunc = context.WithCancel(context.Background()) kubeInformerClient = kubefake.NewClientset() @@ -244,7 +245,8 @@ func TestTLSCertObserverControllerSync(t *testing.T) { }, Spec: supervisorconfigv1alpha1.FederationDomainSpec{ Issuer: "https://bad-secret-issuer.com", - TLS: &supervisorconfigv1alpha1.FederationDomainTLSSpec{SecretName: "bad-tls-secret-name"}, + //nolint:gosec // not a real credential + TLS: &supervisorconfigv1alpha1.FederationDomainTLSSpec{SecretName: "bad-tls-secret-name"}, }, } // Also add one with a URL that cannot be parsed to make sure that the controller is not confused by invalid URLs. diff --git a/internal/controller/supervisorstorage/garbage_collector_test.go b/internal/controller/supervisorstorage/garbage_collector_test.go index 85c150cf9..919592cce 100644 --- a/internal/controller/supervisorstorage/garbage_collector_test.go +++ b/internal/controller/supervisorstorage/garbage_collector_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package supervisorstorage @@ -177,6 +177,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { it.Before(func() { r = require.New(t) + //nolint:gosec // cancelContextCancelFunc is called in the After() cancelContext, cancelContextCancelFunc = context.WithCancel(context.Background()) kubeInformerClient = kubefake.NewClientset() @@ -287,6 +288,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { ProviderUID: "upstream-oidc-provider-uid", ProviderName: "upstream-oidc-provider-name", ProviderType: psession.ProviderTypeOIDC, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamRefreshToken: "fake-upstream-refresh-token", }, @@ -332,6 +334,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { ProviderUID: "upstream-oidc-provider-uid", ProviderName: "upstream-oidc-provider-name", ProviderType: psession.ProviderTypeOIDC, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamRefreshToken: "other-fake-upstream-refresh-token", }, @@ -379,6 +382,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { // The upstream refresh token is only revoked for the active authcode session. idpListerBuilder.RequireExactlyOneCallToRevokeToken(t, "upstream-oidc-provider-name", + //nolint:gosec // not a real credential &oidctestutil.RevokeTokenArgs{ Ctx: syncContext.Context, Token: "fake-upstream-refresh-token", @@ -432,6 +436,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { ProviderUID: "upstream-oidc-provider-uid", ProviderName: "upstream-oidc-provider-name", ProviderType: psession.ProviderTypeOIDC, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamAccessToken: "fake-upstream-access-token", }, @@ -477,6 +482,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { ProviderUID: "upstream-oidc-provider-uid", ProviderName: "upstream-oidc-provider-name", ProviderType: psession.ProviderTypeOIDC, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamAccessToken: "other-fake-upstream-access-token", }, @@ -524,6 +530,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { // The upstream refresh token is only revoked for the active authcode session. idpListerBuilder.RequireExactlyOneCallToRevokeToken(t, "upstream-oidc-provider-name", + //nolint:gosec // not a real credential &oidctestutil.RevokeTokenArgs{ Ctx: syncContext.Context, Token: "fake-upstream-access-token", @@ -577,6 +584,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { ProviderUID: "upstream-oidc-provider-uid", ProviderName: "upstream-oidc-provider-name", ProviderType: psession.ProviderTypeOIDC, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamRefreshToken: "fake-upstream-refresh-token", }, @@ -646,6 +654,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { ProviderUID: "upstream-oidc-provider-uid", ProviderName: "upstream-oidc-provider-name-will-not-match", ProviderType: psession.ProviderTypeOIDC, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamRefreshToken: "fake-upstream-refresh-token", }, @@ -726,6 +735,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { ProviderUID: "upstream-oidc-provider-uid-will-not-match", ProviderName: "upstream-oidc-provider-name", ProviderType: psession.ProviderTypeOIDC, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamRefreshToken: "fake-upstream-refresh-token", }, @@ -806,6 +816,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { ProviderUID: "upstream-oidc-provider-uid", ProviderName: "upstream-oidc-provider-name", ProviderType: psession.ProviderTypeOIDC, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamRefreshToken: "fake-upstream-refresh-token", }, @@ -855,6 +866,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { // Tried to revoke it, although this revocation will fail. idpListerBuilder.RequireExactlyOneCallToRevokeToken(t, "upstream-oidc-provider-name", + //nolint:gosec // not a real credential &oidctestutil.RevokeTokenArgs{ Ctx: syncContext.Context, Token: "fake-upstream-refresh-token", @@ -880,6 +892,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { // Tried to revoke it, although this revocation will fail. idpListerBuilder.RequireExactlyOneCallToRevokeToken(t, "upstream-oidc-provider-name", + //nolint:gosec // not a real credential &oidctestutil.RevokeTokenArgs{ Ctx: syncContext.Context, Token: "fake-upstream-refresh-token", @@ -920,6 +933,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { ProviderUID: "upstream-oidc-provider-uid", ProviderName: "upstream-oidc-provider-name", ProviderType: psession.ProviderTypeOIDC, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamRefreshToken: "fake-upstream-refresh-token", }, @@ -968,6 +982,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { // Tried to revoke it, although this revocation will fail. idpListerBuilder.RequireExactlyOneCallToRevokeToken(t, "upstream-oidc-provider-name", + //nolint:gosec // not a real credential &oidctestutil.RevokeTokenArgs{ Ctx: syncContext.Context, Token: "fake-upstream-refresh-token", @@ -1053,6 +1068,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { ProviderUID: "upstream-oidc-provider-uid", ProviderName: "upstream-oidc-provider-name", ProviderType: psession.ProviderTypeOIDC, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamRefreshToken: "fake-upstream-refresh-token", }, @@ -1100,6 +1116,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { // The upstream refresh token is only revoked for the downstream session which had offline_access granted. idpListerBuilder.RequireExactlyOneCallToRevokeToken(t, "upstream-oidc-provider-name", + //nolint:gosec // not a real credential &oidctestutil.RevokeTokenArgs{ Ctx: syncContext.Context, Token: "fake-upstream-refresh-token", @@ -1198,6 +1215,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { ProviderUID: "upstream-oidc-provider-uid", ProviderName: "upstream-oidc-provider-name", ProviderType: psession.ProviderTypeOIDC, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamAccessToken: "fake-upstream-access-token", }, @@ -1245,6 +1263,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { // The upstream refresh token is only revoked for the downstream session which had offline_access granted. idpListerBuilder.RequireExactlyOneCallToRevokeToken(t, "upstream-oidc-provider-name", + //nolint:gosec // not a real credential &oidctestutil.RevokeTokenArgs{ Ctx: syncContext.Context, Token: "fake-upstream-access-token", @@ -1297,6 +1316,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { ProviderUID: "upstream-oidc-provider-uid", ProviderName: "upstream-oidc-provider-name", ProviderType: psession.ProviderTypeOIDC, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamRefreshToken: "fake-upstream-refresh-token", }, @@ -1344,6 +1364,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { // The upstream refresh token is revoked. idpListerBuilder.RequireExactlyOneCallToRevokeToken(t, "upstream-oidc-provider-name", + //nolint:gosec // not a real credential &oidctestutil.RevokeTokenArgs{ Ctx: syncContext.Context, Token: "fake-upstream-refresh-token", @@ -1389,6 +1410,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { ProviderUID: "upstream-oidc-provider-uid", ProviderName: "upstream-oidc-provider-name", ProviderType: psession.ProviderTypeOIDC, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamAccessToken: "fake-upstream-access-token", }, @@ -1436,6 +1458,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) { // The upstream refresh token is revoked. idpListerBuilder.RequireExactlyOneCallToRevokeToken(t, "upstream-oidc-provider-name", + //nolint:gosec // not a real credential &oidctestutil.RevokeTokenArgs{ Ctx: syncContext.Context, Token: "fake-upstream-access-token", diff --git a/internal/crypto/ptls/ptls_test.go b/internal/crypto/ptls/ptls_test.go index f38ca3b99..531c119ff 100644 --- a/internal/crypto/ptls/ptls_test.go +++ b/internal/crypto/ptls/ptls_test.go @@ -1,4 +1,4 @@ -// Copyright 2021-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2021-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package ptls @@ -43,7 +43,7 @@ func TestMerge(t *testing.T) { { name: "default without NextProtos", tlsConfigFunc: Default, - tlsConfig: &tls.Config{ //nolint:gosec // not concerned with TLS MinVersion here + tlsConfig: &tls.Config{ ServerName: "something-to-check-passthrough", }, want: &tls.Config{ @@ -63,7 +63,7 @@ func TestMerge(t *testing.T) { { name: "default with NextProtos", tlsConfigFunc: Default, - tlsConfig: &tls.Config{ //nolint:gosec // not concerned with TLS MinVersion here + tlsConfig: &tls.Config{ ServerName: "a different thing for passthrough", NextProtos: []string{"panda"}, }, @@ -84,7 +84,7 @@ func TestMerge(t *testing.T) { { name: "secure without NextProtos", tlsConfigFunc: Secure, - tlsConfig: &tls.Config{ //nolint:gosec // not concerned with TLS MinVersion here + tlsConfig: &tls.Config{ ServerName: "something-to-check-passthrough", }, want: &tls.Config{ @@ -97,7 +97,7 @@ func TestMerge(t *testing.T) { { name: "secure with NextProtos", tlsConfigFunc: Secure, - tlsConfig: &tls.Config{ //nolint:gosec // not concerned with TLS MinVersion here + tlsConfig: &tls.Config{ ServerName: "a different thing for passthrough", NextProtos: []string{"panda"}, }, @@ -111,7 +111,7 @@ func TestMerge(t *testing.T) { { name: "default ldap without NextProtos", tlsConfigFunc: DefaultLDAP, - tlsConfig: &tls.Config{ //nolint:gosec // not concerned with TLS MinVersion here + tlsConfig: &tls.Config{ ServerName: "something-to-check-passthrough", }, want: &tls.Config{ diff --git a/internal/execcredcache/execcredcache_test.go b/internal/execcredcache/execcredcache_test.go index d7831ac8e..7000d6ab2 100644 --- a/internal/execcredcache/execcredcache_test.go +++ b/internal/execcredcache/execcredcache_test.go @@ -1,4 +1,4 @@ -// Copyright 2021-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2021-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package execcredcache @@ -368,6 +368,7 @@ func (e *errorCollector) require(want []string, subs ...string) { require.Len(e.t, e.saw, len(want)) for i, w := range want { for i := 0; i < len(subs); i += 2 { + //nolint:gosec // these indices will not be out of bounds as long as callers pass the expected number of arguments w = strings.ReplaceAll(w, subs[i], subs[i+1]) } require.EqualError(e.t, e.saw[i], w) diff --git a/internal/federationdomain/endpoints/auth/auth_handler_test.go b/internal/federationdomain/endpoints/auth/auth_handler_test.go index 206176e11..73a2fa9ce 100644 --- a/internal/federationdomain/endpoints/auth/auth_handler_test.go +++ b/internal/federationdomain/endpoints/auth/auth_handler_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package auth @@ -4107,7 +4107,7 @@ func TestAuthorizationEndpoint(t *testing.T) { //nolint:gocyclo } reqContext := context.WithValue(context.Background(), struct{ name string }{name: "test"}, "request-context") - req := httptest.NewRequest(test.method, test.path, strings.NewReader(test.body)).WithContext(reqContext) + req := httptest.NewRequestWithContext(reqContext, test.method, test.path, strings.NewReader(test.body)) req.Header.Set("Content-Type", test.contentType) if test.csrfCookie != "" { req.Header.Set("Cookie", test.csrfCookie) diff --git a/internal/federationdomain/endpoints/callback/callback_handler_test.go b/internal/federationdomain/endpoints/callback/callback_handler_test.go index 03d7bef1d..09edb038d 100644 --- a/internal/federationdomain/endpoints/callback/callback_handler_test.go +++ b/internal/federationdomain/endpoints/callback/callback_handler_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package callback @@ -2202,7 +2202,7 @@ func TestCallbackEndpoint(t *testing.T) { if test.body != "" { bodyReader = strings.NewReader(test.body) } - req := httptest.NewRequest(test.method, test.path, bodyReader).WithContext(reqContext) + req := httptest.NewRequestWithContext(reqContext, test.method, test.path, bodyReader) if test.csrfCookie != "" { req.Header.Set("Cookie", test.csrfCookie) } diff --git a/internal/federationdomain/endpoints/chooseidp/choose_idp_handler_test.go b/internal/federationdomain/endpoints/chooseidp/choose_idp_handler_test.go index de6b687e0..f20491137 100644 --- a/internal/federationdomain/endpoints/chooseidp/choose_idp_handler_test.go +++ b/internal/federationdomain/endpoints/chooseidp/choose_idp_handler_test.go @@ -1,4 +1,4 @@ -// Copyright 2023-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2023-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package chooseidp @@ -137,7 +137,7 @@ func TestChooseIDPHandler(t *testing.T) { handler := NewHandler(testIssuer, test.idps) - req := httptest.NewRequest(test.method, test.reqTarget, nil) + req := httptest.NewRequestWithContext(t.Context(), test.method, test.reqTarget, nil) rsp := httptest.NewRecorder() handler.ServeHTTP(rsp, req) diff --git a/internal/federationdomain/endpoints/discovery/discovery_handler_test.go b/internal/federationdomain/endpoints/discovery/discovery_handler_test.go index 4092aced0..fa6175c86 100644 --- a/internal/federationdomain/endpoints/discovery/discovery_handler_test.go +++ b/internal/federationdomain/endpoints/discovery/discovery_handler_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package discovery @@ -67,7 +67,7 @@ func TestDiscovery(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { handler := NewHandler(test.issuer) - req := httptest.NewRequest(test.method, test.path, nil) + req := httptest.NewRequestWithContext(t.Context(), test.method, test.path, nil) rsp := httptest.NewRecorder() handler.ServeHTTP(rsp, req) diff --git a/internal/federationdomain/endpoints/idpdiscovery/idp_discovery_handler_test.go b/internal/federationdomain/endpoints/idpdiscovery/idp_discovery_handler_test.go index cd386d457..0eaf3e04e 100644 --- a/internal/federationdomain/endpoints/idpdiscovery/idp_discovery_handler_test.go +++ b/internal/federationdomain/endpoints/idpdiscovery/idp_discovery_handler_test.go @@ -1,4 +1,4 @@ -// Copyright 2021-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2021-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package idpdiscovery @@ -134,7 +134,7 @@ func TestIDPDiscovery(t *testing.T) { t.Run(test.name, func(t *testing.T) { require.NotNil(t, test.idpLister) handler := NewHandler(test.idpLister) - req := httptest.NewRequest(test.method, test.path, nil) + req := httptest.NewRequestWithContext(t.Context(), test.method, test.path, nil) rsp := httptest.NewRecorder() handler.ServeHTTP(rsp, req) diff --git a/internal/federationdomain/endpoints/jwks/jwks_handler_test.go b/internal/federationdomain/endpoints/jwks/jwks_handler_test.go index 5e6abb1d3..d3c5f1cdf 100644 --- a/internal/federationdomain/endpoints/jwks/jwks_handler_test.go +++ b/internal/federationdomain/endpoints/jwks/jwks_handler_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package jwks @@ -79,7 +79,7 @@ func TestJWKSEndpoint(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { handler := NewHandler(test.issuer, test.provider) - req := httptest.NewRequest(test.method, test.path, nil) + req := httptest.NewRequestWithContext(t.Context(), test.method, test.path, nil) rsp := httptest.NewRecorder() handler.ServeHTTP(rsp, req) diff --git a/internal/federationdomain/endpoints/login/get_login_handler_test.go b/internal/federationdomain/endpoints/login/get_login_handler_test.go index 50fa5bddd..676e31a5e 100644 --- a/internal/federationdomain/endpoints/login/get_login_handler_test.go +++ b/internal/federationdomain/endpoints/login/get_login_handler_test.go @@ -1,4 +1,4 @@ -// Copyright 2022-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2022-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package login @@ -103,7 +103,7 @@ func TestGetLogin(t *testing.T) { if tt.errParam != "" { target += "&err=" + tt.errParam } - req := httptest.NewRequest(http.MethodGet, target, nil) + req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, target, nil) rsp := httptest.NewRecorder() err := handler(rsp, req, tt.encodedState, tt.decodedState) require.NoError(t, err) diff --git a/internal/federationdomain/endpoints/login/login_handler_test.go b/internal/federationdomain/endpoints/login/login_handler_test.go index 5d9560c73..a1a0deb6f 100644 --- a/internal/federationdomain/endpoints/login/login_handler_test.go +++ b/internal/federationdomain/endpoints/login/login_handler_test.go @@ -1,4 +1,4 @@ -// Copyright 2022-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2022-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package login @@ -461,7 +461,7 @@ func TestLoginEndpoint(t *testing.T) { t.Run(test.name, func(t *testing.T) { t.Parallel() - req := httptest.NewRequest(test.method, test.path, nil) + req := httptest.NewRequestWithContext(t.Context(), test.method, test.path, nil) if test.csrfCookie != "" { req.Header.Set("Cookie", test.csrfCookie) } diff --git a/internal/federationdomain/endpoints/login/post_login_handler.go b/internal/federationdomain/endpoints/login/post_login_handler.go index 230a67f1d..023ece1f6 100644 --- a/internal/federationdomain/endpoints/login/post_login_handler.go +++ b/internal/federationdomain/endpoints/login/post_login_handler.go @@ -1,4 +1,4 @@ -// Copyright 2022-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2022-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package login @@ -72,6 +72,7 @@ func NewPostHandler( downstreamsession.AutoApproveScopes(authorizeRequester) // Get the username and password form params from the POST body. + r.Body = http.MaxBytesReader(w, r.Body, 1<<20) // Limit request body size to 1 MB submittedUsername := r.PostFormValue(loginurl.UsernameParamName) submittedPassword := r.PostFormValue(loginurl.PasswordParamName) diff --git a/internal/federationdomain/endpoints/login/post_login_handler_test.go b/internal/federationdomain/endpoints/login/post_login_handler_test.go index 2b2bc0e7b..4bdb5684f 100644 --- a/internal/federationdomain/endpoints/login/post_login_handler_test.go +++ b/internal/federationdomain/endpoints/login/post_login_handler_test.go @@ -1,4 +1,4 @@ -// Copyright 2022-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2022-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package login @@ -1316,7 +1316,7 @@ func TestPostLoginEndpoint(t *testing.T) { jwksProviderIsUnused := jwks.NewDynamicJWKSProvider() oauthHelper := oidc.FositeOauth2Helper(kubeOauthStore, downstreamIssuer, hmacSecretFunc, jwksProviderIsUnused, timeoutsConfiguration) - req := httptest.NewRequest(http.MethodPost, "/ignored", strings.NewReader(tt.formParams.Encode())) + req := httptest.NewRequestWithContext(t.Context(), http.MethodPost, "/ignored", strings.NewReader(tt.formParams.Encode())) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") if tt.reqURIQuery != nil { req.URL.RawQuery = tt.reqURIQuery.Encode() diff --git a/internal/federationdomain/endpoints/token/token_handler_test.go b/internal/federationdomain/endpoints/token/token_handler_test.go index 3b321928f..2851730e3 100644 --- a/internal/federationdomain/endpoints/token/token_handler_test.go +++ b/internal/federationdomain/endpoints/token/token_handler_test.go @@ -1100,7 +1100,7 @@ func TestTokenEndpointWhenAuthcodeIsUsedTwice(t *testing.T) { // // Fosite will also revoke the access token as is recommended by the OIDC spec. Currently, we don't // delete the OIDC storage...but we probably should. - req := httptest.NewRequest("POST", "/path/shouldn't/matter", happyAuthcodeRequestBody(authCode).ReadCloser()) + req := httptest.NewRequestWithContext(t.Context(), "POST", "/path/shouldn't/matter", happyAuthcodeRequestBody(authCode).ReadCloser()) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") reusedAuthcodeResponse := httptest.NewRecorder() approxRequestTime := time.Now() @@ -1255,6 +1255,7 @@ func TestTokenEndpointTokenExchange(t *testing.T) { // tests for grant_type "urn wantAuditLogs: func(sessionID string, idToken string) []testutil.WantedAuditLog { return []testutil.WantedAuditLog{ testutil.WantAuditLog("HTTP Request Parameters", map[string]any{ + //nolint:gosec // no credentials here "params": map[string]any{ "audience": "some-workload-cluster", "client_id": "pinniped-cli", @@ -1447,6 +1448,7 @@ func TestTokenEndpointTokenExchange(t *testing.T) { // tests for grant_type "urn wantAuditLogs: func(sessionID string, idToken string) []testutil.WantedAuditLog { return []testutil.WantedAuditLog{ testutil.WantAuditLog("HTTP Request Parameters", map[string]any{ + //nolint:gosec // no credentials here "params": map[string]any{ "audience": "some-workload-cluster", "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", @@ -1558,6 +1560,7 @@ func TestTokenEndpointTokenExchange(t *testing.T) { // tests for grant_type "urn wantErrorDescContains: "Missing 'audience' parameter.", wantAuditLogs: func(sessionID string, idToken string) []testutil.WantedAuditLog { return []testutil.WantedAuditLog{ + //nolint:gosec // no credentials here testutil.WantAuditLog("HTTP Request Parameters", map[string]any{ "params": map[string]any{ "audience": "", // make it obvious @@ -1848,7 +1851,7 @@ func TestTokenEndpointTokenExchange(t *testing.T) { // tests for grant_type "urn test.modifyRequestParams(t, request.Form) } - req := httptest.NewRequest("POST", "/token/exchange/path/shouldn't/matter", body(request.Form).ReadCloser()) + req := httptest.NewRequestWithContext(t.Context(), "POST", "/token/exchange/path/shouldn't/matter", body(request.Form).ReadCloser()) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req, _ = auditid.NewRequestWithAuditID(req, func() string { return "fake-token-exchange-audit-id" }) rsp = httptest.NewRecorder() @@ -5051,7 +5054,7 @@ func TestRefreshGrant(t *testing.T) { } reqContextWarningRecorder := &TestWarningRecorder{} - req := httptest.NewRequest("POST", "/path/shouldn't/matter", + req := httptest.NewRequestWithContext(t.Context(), "POST", "/path/shouldn't/matter", happyRefreshRequestBody(firstRefreshToken).ReadCloser()). WithContext(warning.WithWarningRecorder( context.WithValue(context.Background(), struct{ name string }{name: "test"}, "request-context"), @@ -5262,7 +5265,7 @@ func exchangeAuthcodeForTokens( // Assert the number of all secrets, excluding any OIDCClient's storage secret, since those are not related to session storage. testutil.RequireNumberOfSecretsExcludingLabelSelector(t, secrets, labels.Set{crud.SecretLabelKey: oidcclientsecretstorage.TypeLabelValue}, 2+expectedNumberOfIDSessionsStored) - req := httptest.NewRequest("POST", "/path/shouldn't/matter", happyAuthcodeRequestBody(authCode).ReadCloser()) + req := httptest.NewRequestWithContext(t.Context(), "POST", "/path/shouldn't/matter", happyAuthcodeRequestBody(authCode).ReadCloser()) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") if test.modifyTokenRequest != nil { test.modifyTokenRequest(req, authCode) diff --git a/internal/federationdomain/endpointsmanager/manager_test.go b/internal/federationdomain/endpointsmanager/manager_test.go index cc02e7e0a..51f44265a 100644 --- a/internal/federationdomain/endpointsmanager/manager_test.go +++ b/internal/federationdomain/endpointsmanager/manager_test.go @@ -73,11 +73,11 @@ func TestManager(t *testing.T) { ) newGetRequest := func(url string) *http.Request { - return httptest.NewRequest(http.MethodGet, url, nil) + return httptest.NewRequestWithContext(t.Context(), http.MethodGet, url, nil) } newPostRequest := func(url, body string) *http.Request { - req := httptest.NewRequest(http.MethodPost, url, strings.NewReader(body)) + req := httptest.NewRequestWithContext(t.Context(), http.MethodPost, url, strings.NewReader(body)) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") return req } diff --git a/internal/federationdomain/federationdomainproviders/federation_domain_issuer_test.go b/internal/federationdomain/federationdomainproviders/federation_domain_issuer_test.go index 05967dca0..0ea676066 100644 --- a/internal/federationdomain/federationdomainproviders/federation_domain_issuer_test.go +++ b/internal/federationdomain/federationdomainproviders/federation_domain_issuer_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package federationdomainproviders @@ -58,6 +58,7 @@ func TestFederationDomainIssuerValidations(t *testing.T) { issuer: "https://username@tuna.com", wantError: `issuer must not have username or password`, }, + //nolint:gosec // not a real credential { name: "password", issuer: "https://username:password@tuna.com", diff --git a/internal/federationdomain/resolvedprovider/resolvedgithub/resolved_github_provider_test.go b/internal/federationdomain/resolvedprovider/resolvedgithub/resolved_github_provider_test.go index 409a22cf1..82e8980a3 100644 --- a/internal/federationdomain/resolvedprovider/resolvedgithub/resolved_github_provider_test.go +++ b/internal/federationdomain/resolvedprovider/resolvedgithub/resolved_github_provider_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package resolvedgithub @@ -37,10 +37,12 @@ func TestFederationDomainResolvedGitHubIdentityProvider(t *testing.T) { GroupNameAttribute: idpv1alpha1.GitHubUseTeamSlugForGroupName, AllowedOrganizations: setutil.NewCaseInsensitiveSet("org1", "org2"), HttpClient: nil, // not needed yet for this test + //nolint:gosec // not a real credential OAuth2Config: &oauth2.Config{ ClientID: "fake-client-id", ClientSecret: "fake-client-secret", Scopes: []string{"read:user", "read:org"}, + //nolint:gosec // no credentials here Endpoint: oauth2.Endpoint{ AuthURL: "https://fake-authorization-url", DeviceAuthURL: "", @@ -67,11 +69,11 @@ func TestFederationDomainResolvedGitHubIdentityProvider(t *testing.T) { originalCustomSession := &psession.CustomSessionData{ Username: "fake-username", UpstreamUsername: "fake-upstream-username", - GitHub: &psession.GitHubSessionData{UpstreamAccessToken: "fake-upstream-access-token"}, + GitHub: &psession.GitHubSessionData{UpstreamAccessToken: "fake-upstream-access-token"}, //nolint:gosec // not a real credential } clonedCustomSession := subject.CloneIDPSpecificSessionDataFromSession(originalCustomSession) require.Equal(t, - &psession.GitHubSessionData{UpstreamAccessToken: "fake-upstream-access-token"}, + &psession.GitHubSessionData{UpstreamAccessToken: "fake-upstream-access-token"}, //nolint:gosec // not a real credential clonedCustomSession, ) require.NotSame(t, originalCustomSession, clonedCustomSession) @@ -379,7 +381,7 @@ func TestUpstreamRefresh(t *testing.T) { UpstreamUsername: "initial-username", UpstreamGroups: []string{"initial-group1", "initial-group2"}, DownstreamSubject: "https://fake-downstream-subject", - IDPSpecificSessionData: &psession.GitHubSessionData{UpstreamAccessToken: ""}, // missing token + IDPSpecificSessionData: &psession.GitHubSessionData{UpstreamAccessToken: ""}, // missing token //nolint:gosec // not a real credential }, idpDisplayName: "fake-display-name", wantGetUserCall: false, diff --git a/internal/fositestorage/accesstoken/accesstoken_test.go b/internal/fositestorage/accesstoken/accesstoken_test.go index 2cbda7dd0..48d19191c 100644 --- a/internal/fositestorage/accesstoken/accesstoken_test.go +++ b/internal/fositestorage/accesstoken/accesstoken_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package accesstoken @@ -344,6 +344,7 @@ func TestReadFromSecret(t *testing.T) { ProviderType: "fake-provider-type", UpstreamUsername: "fake-upstream-username", UpstreamGroups: []string{"fake-upstream-group1", "fake-upstream-group2"}, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamRefreshToken: "fake-upstream-refresh-token", }, diff --git a/internal/fositestorage/authorizationcode/authorizationcode_test.go b/internal/fositestorage/authorizationcode/authorizationcode_test.go index 81df23a4e..2c1c62a90 100644 --- a/internal/fositestorage/authorizationcode/authorizationcode_test.go +++ b/internal/fositestorage/authorizationcode/authorizationcode_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package authorizationcode @@ -480,6 +480,7 @@ func TestReadFromSecret(t *testing.T) { ProviderType: "fake-provider-type", UpstreamUsername: "fake-upstream-username", UpstreamGroups: []string{"fake-upstream-group1", "fake-upstream-group2"}, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamRefreshToken: "fake-upstream-refresh-token", }, diff --git a/internal/fositestorage/refreshtoken/refreshtoken_test.go b/internal/fositestorage/refreshtoken/refreshtoken_test.go index 4bb7d087f..1fd11c91e 100644 --- a/internal/fositestorage/refreshtoken/refreshtoken_test.go +++ b/internal/fositestorage/refreshtoken/refreshtoken_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package refreshtoken @@ -401,6 +401,7 @@ func TestReadFromSecret(t *testing.T) { ProviderType: "fake-provider-type", UpstreamUsername: "fake-upstream-username", UpstreamGroups: []string{"fake-upstream-group1", "fake-upstream-group2"}, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamRefreshToken: "fake-upstream-refresh-token", }, diff --git a/internal/kubeclient/kubeclient.go b/internal/kubeclient/kubeclient.go index 6c70eea9f..3997e4cc1 100644 --- a/internal/kubeclient/kubeclient.go +++ b/internal/kubeclient/kubeclient.go @@ -1,4 +1,4 @@ -// Copyright 2021-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2021-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package kubeclient @@ -221,7 +221,6 @@ func assertTransport(rt http.RoundTripper, tlsConfigFunc ptls.ConfigFunc) error tlsConfigCopy := tlsConfig.Clone() ptls.Merge(tlsConfigFunc, tlsConfigCopy) // only mutate the copy - //nolint:gosec // the empty TLS config here is not used if diff := cmp.Diff(tlsConfigCopy, tlsConfig, cmpopts.IgnoreUnexported(tls.Config{}, x509.CertPool{}), cmpopts.IgnoreFields(tls.Config{}, "GetClientCertificate"), diff --git a/internal/kubeclient/roundtrip.go b/internal/kubeclient/roundtrip.go index bc4a5bd0d..250238316 100644 --- a/internal/kubeclient/roundtrip.go +++ b/internal/kubeclient/roundtrip.go @@ -1,4 +1,4 @@ -// Copyright 2021-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2021-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package kubeclient @@ -250,6 +250,7 @@ func handleCreateOrUpdate( } // simplest way to reuse the body creation logic + //nolint:gosec // not worried about untrusted user input in req because we are in a roundtripper for a req that we were going to make anyway newReqForBody, err := http.NewRequestWithContext(req.Context(), req.Method, reqURL.String(), bytes.NewReader(newData)) if err != nil { return true, nil, fmt.Errorf("failed to create new req for body: %w", err) // this should never happen diff --git a/internal/localuserauthenticator/localuserauthenticator.go b/internal/localuserauthenticator/localuserauthenticator.go index c648e9fa2..001a160ed 100644 --- a/internal/localuserauthenticator/localuserauthenticator.go +++ b/internal/localuserauthenticator/localuserauthenticator.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // Package localuserauthenticator provides a authentication webhook program. @@ -91,6 +91,7 @@ func (w *webhook) start(ctx context.Context, l net.Listener) error { errCh <- server.ServeTLS(l, "", "") }() + //nolint:gosec // using background context because we can't use ctx here since it is already done go func() { select { case err := <-errCh: diff --git a/internal/net/phttp/warning.go b/internal/net/phttp/warning.go index a7c16f0c6..fb3646c57 100644 --- a/internal/net/phttp/warning.go +++ b/internal/net/phttp/warning.go @@ -1,4 +1,4 @@ -// Copyright 2021-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2021-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package phttp @@ -40,6 +40,7 @@ func getWarningHandler() rest.WarningHandler { // the client-go rest.WarningHandlers all log warnings with non-empty message and code=299, agent is ignored // no deduplication or color output when running from a non-terminal such as a pod + //nolint:gosec // casting to an int is the documented way to call this function if isTerm := term.IsTerminal(int(os.Stderr.Fd())); !isTerm { return rest.WarningLogger{} } diff --git a/internal/supervisor/server/server.go b/internal/supervisor/server/server.go index 71a1d273f..a9d958088 100644 --- a/internal/supervisor/server/server.go +++ b/internal/supervisor/server/server.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // Package server defines the entrypoint for the Pinniped Supervisor server. @@ -102,6 +102,7 @@ func startServer(ctx context.Context, shutdown *sync.WaitGroup, l net.Listener, }() shutdown.Add(1) + //nolint:gosec // using background context because we can't use ctx here because it is already done go func() { defer shutdown.Done() diff --git a/internal/testutil/psession.go b/internal/testutil/psession.go index 6bfa9a6ba..0321555ad 100644 --- a/internal/testutil/psession.go +++ b/internal/testutil/psession.go @@ -1,4 +1,4 @@ -// Copyright 2021-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2021-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package testutil @@ -30,6 +30,7 @@ func NewFakePinnipedSession() *psession.PinnipedSession { ProviderName: "fake-provider-name", UpstreamUsername: "fake-upstream-username", UpstreamGroups: []string{"fake-upstream-group1", "fake-upstream-group2"}, + //nolint:gosec // not a real credential OIDC: &psession.OIDCSessionData{ UpstreamRefreshToken: "fake-upstream-refresh-token", UpstreamSubject: "some-subject", diff --git a/internal/testutil/totp/totp_test.go b/internal/testutil/totp/totp_test.go index 6a7fcdd75..7d4655e45 100644 --- a/internal/testutil/totp/totp_test.go +++ b/internal/testutil/totp/totp_test.go @@ -1,4 +1,4 @@ -// Copyright 2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2024-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package totp @@ -18,6 +18,7 @@ func TestGenerateOTPCode(t *testing.T) { wantCode string wantRemainingLifetimeSeconds int64 }{ + //nolint:gosec // not a real credential { name: "Use a token from online example", token: "JBSWY3DPEHPK3PXP", // https://github.com/pquerna/otp/blob/3357de7c04813a328d6a1e4a514854213e0f8ce8/totp/totp.go#L180 @@ -25,6 +26,7 @@ func TestGenerateOTPCode(t *testing.T) { wantCode: "780919", wantRemainingLifetimeSeconds: 11, }, + //nolint:gosec // not a real credential { name: "Use a token that was randomly generated", token: "EDAYKXL3TEYZNQ3O4N5KPSUAQQLZYUJG", diff --git a/internal/upstreamgithub/upstreamgithub_test.go b/internal/upstreamgithub/upstreamgithub_test.go index a1b9af26c..7b72fa4d1 100644 --- a/internal/upstreamgithub/upstreamgithub_test.go +++ b/internal/upstreamgithub/upstreamgithub_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package upstreamgithub @@ -34,6 +34,7 @@ func TestGitHubProvider(t *testing.T) { APIBaseURL: "https://fake-base-url", UsernameAttribute: "fake-username-attribute", GroupNameAttribute: "fake-group-name-attribute", + //nolint:gosec // not a real credential OAuth2Config: &oauth2.Config{ ClientID: "fake-client-id", ClientSecret: "fake-client-secret", @@ -57,10 +58,12 @@ func TestGitHubProvider(t *testing.T) { APIBaseURL: "https://fake-base-url", UsernameAttribute: "fake-username-attribute", GroupNameAttribute: "fake-group-name-attribute", + //nolint:gosec // not a real credential OAuth2Config: &oauth2.Config{ ClientID: "fake-client-id", ClientSecret: "fake-client-secret", Scopes: []string{"scope1", "scope2"}, + //nolint:gosec // no credentials here Endpoint: oauth2.Endpoint{ AuthURL: "https://fake-authorization-url", DeviceAuthURL: "", @@ -123,6 +126,7 @@ func TestExchangeAuthcode(t *testing.T) { require.NotEmpty(t, r.Header.Get("Content-Length")) // Get the params. + //nolint:gosec // this is a test, so we don't care about limiting request body size err := r.ParseForm() require.NoError(t, err) params := r.PostForm @@ -158,6 +162,7 @@ func TestExchangeAuthcode(t *testing.T) { require.NoError(t, err) subject := New(ProviderConfig{ + //nolint:gosec // not a real credential OAuth2Config: &oauth2.Config{ ClientID: "fake-client-id", ClientSecret: "fake-client-secret", diff --git a/internal/upstreamoidc/upstreamoidc_test.go b/internal/upstreamoidc/upstreamoidc_test.go index 02d4ef804..63a5ad23e 100644 --- a/internal/upstreamoidc/upstreamoidc_test.go +++ b/internal/upstreamoidc/upstreamoidc_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package upstreamoidc @@ -284,6 +284,7 @@ func TestProviderConfig(t *testing.T) { t.Run(tt.name, func(t *testing.T) { tokenServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { require.Equal(t, http.MethodPost, r.Method) + //nolint:gosec // this is a test, so we don't care about limiting request body size require.NoError(t, r.ParseForm()) require.Equal(t, 6, len(r.Form)) require.Equal(t, "password", r.Form.Get("grant_type")) @@ -456,6 +457,7 @@ func TestProviderConfig(t *testing.T) { t.Run(tt.name, func(t *testing.T) { tokenServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { require.Equal(t, http.MethodPost, r.Method) + //nolint:gosec // this is a test, so we don't care about limiting request body size require.NoError(t, r.ParseForm()) require.Equal(t, 4, len(r.Form)) require.Equal(t, "test-client-id", r.Form.Get("client_id")) @@ -694,6 +696,7 @@ func TestProviderConfig(t *testing.T) { numRequests++ require.LessOrEqual(t, numRequests, 2) require.Equal(t, http.MethodPost, r.Method) + //nolint:gosec // this is a test, so we don't care about limiting request body size require.NoError(t, r.ParseForm()) if numRequests == 1 { // First request should use client_id/client_secret params. @@ -929,7 +932,8 @@ func TestProviderConfig(t *testing.T) { }, }, { - name: "claims from userinfo override id token claims", + name: "claims from userinfo override id token claims", + //nolint:gosec // not a real credential tok: testTokenWithoutIDToken.WithExtra(map[string]any{"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzb21lLXN1YmplY3QiLCJuYW1lIjoiSm9obiBEb2UiLCJpc3MiOiJzb21lLWlzc3VlciIsIm5vbmNlIjoic29tZS1ub25jZSJ9.sBWi3_4cfGwrmMFZWkCghw4uvCnHN35h9xNX1gkwOtj6Oz_yKqpj7wfO4AqeWsRyrDGnkmIZbVuhAAJqPSi4GlNzN4NU8zh53PGDUpFlpDI1dvqDjIRb9iIEJpRIj34--Sz41H0ooxviIzvUdZFvQlaSzLOqgjR3ddHe2urhbtUuz_DsabP84AWo2DSg0y3ull6DRvk_DvzC6HNN8JwVi08fFvvV9BVq8kjdVeob7gajJkuGSTjsxNZGs5rbBuxBx0MZTQ8boR1fDNdG70GoIb4SsCoBSs7pZxtmGZPHInteY1SilHDDDmpQuE-LvSmvvPN_Cyk1d3eS-IR7hBbCAA"}), nonce: "some-nonce", requireIDToken: true, @@ -944,6 +948,7 @@ func TestProviderConfig(t *testing.T) { RefreshToken: &oidctypes.RefreshToken{ Token: "test-initial-refresh-token", }, + //nolint:gosec // not a real credential IDToken: &oidctypes.IDToken{ Token: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzb21lLXN1YmplY3QiLCJuYW1lIjoiSm9obiBEb2UiLCJpc3MiOiJzb21lLWlzc3VlciIsIm5vbmNlIjoic29tZS1ub25jZSJ9.sBWi3_4cfGwrmMFZWkCghw4uvCnHN35h9xNX1gkwOtj6Oz_yKqpj7wfO4AqeWsRyrDGnkmIZbVuhAAJqPSi4GlNzN4NU8zh53PGDUpFlpDI1dvqDjIRb9iIEJpRIj34--Sz41H0ooxviIzvUdZFvQlaSzLOqgjR3ddHe2urhbtUuz_DsabP84AWo2DSg0y3ull6DRvk_DvzC6HNN8JwVi08fFvvV9BVq8kjdVeob7gajJkuGSTjsxNZGs5rbBuxBx0MZTQ8boR1fDNdG70GoIb4SsCoBSs7pZxtmGZPHInteY1SilHDDDmpQuE-LvSmvvPN_Cyk1d3eS-IR7hBbCAA", Claims: map[string]any{ @@ -1071,6 +1076,7 @@ func TestProviderConfig(t *testing.T) { userInfo: forceUserInfoWithClaims("some-other-subject", `{"name": "Pinny TheSeal", "sub": "some-other-subject"}`), wantErr: "could not fetch user info claims: userinfo 'sub' claim (some-other-subject) did not match id_token 'sub' claim (some-subject)", }, + //nolint:gosec // not a real credential { name: "invalid id token", tok: testTokenWithoutIDToken.WithExtra(map[string]any{"id_token": "not-an-id-token"}), @@ -1133,6 +1139,7 @@ func TestProviderConfig(t *testing.T) { userInfo: forceUserInfoWithClaims("some-subject", `{"name": "Pinny TheSeal", "sub": "some-subject"}`), wantErr: "received response missing ID token", }, + //nolint:gosec // not a real credential { name: "id token missing subject, skip userinfo check", tok: testTokenWithoutIDToken.WithExtra(map[string]any{"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJpc3MiOiJzb21lLWlzc3VlciIsIm5vbmNlIjoic29tZS1ub25jZSJ9.aIhrhikAnQ4Mb1g6RAT08qqflT2LLLi2yj4F2S4zud8nYad4tfEd2ITVJ4Njdjf70ubqyzZ6XxojtC4OqaWbDaQOcd95sd3PW58SYrf4NMvEStFkcMG0HMhJEZLVGnuJQstuq3G9h5Z5bFCkx4mFNo5ho_isBWyHpk-uF14duXXlIDB10SnyZ9dRbcmu-3mMOq0g4oCUPEDiHWkv-Rf70Mk0harL2xvcpxlSMLK4glDfiiki5gl6IReIo4rTVosXAqv3JmjLDeVLtJQRG6F8YcIlDCIfUEUfk0GeYacBVjoDIO570ywVJy1LGvyUuvgXNQUjq2JgzCfb8HWGp7iJdQ"}), @@ -1149,6 +1156,7 @@ func TestProviderConfig(t *testing.T) { RefreshToken: &oidctypes.RefreshToken{ Token: "test-initial-refresh-token", }, + //nolint:gosec // not a real credential IDToken: &oidctypes.IDToken{ Token: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJpc3MiOiJzb21lLWlzc3VlciIsIm5vbmNlIjoic29tZS1ub25jZSJ9.aIhrhikAnQ4Mb1g6RAT08qqflT2LLLi2yj4F2S4zud8nYad4tfEd2ITVJ4Njdjf70ubqyzZ6XxojtC4OqaWbDaQOcd95sd3PW58SYrf4NMvEStFkcMG0HMhJEZLVGnuJQstuq3G9h5Z5bFCkx4mFNo5ho_isBWyHpk-uF14duXXlIDB10SnyZ9dRbcmu-3mMOq0g4oCUPEDiHWkv-Rf70Mk0harL2xvcpxlSMLK4glDfiiki5gl6IReIo4rTVosXAqv3JmjLDeVLtJQRG6F8YcIlDCIfUEUfk0GeYacBVjoDIO570ywVJy1LGvyUuvgXNQUjq2JgzCfb8HWGp7iJdQ", Claims: map[string]any{ @@ -1170,6 +1178,7 @@ func TestProviderConfig(t *testing.T) { Config: &oauth2.Config{ ClientID: "test-client-id", ClientSecret: "test-client-secret", + //nolint:gosec // no credential here Endpoint: oauth2.Endpoint{ AuthURL: "https://example.com", TokenURL: "https://example.com", @@ -1446,6 +1455,7 @@ func TestProviderConfig(t *testing.T) { t.Run(tt.name, func(t *testing.T) { tokenServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { require.Equal(t, http.MethodPost, r.Method) + //nolint:gosec // this is a test, so we don't care about limiting request body size require.NoError(t, r.ParseForm()) require.Len(t, r.Form, 6) require.Equal(t, "test-client-id", r.Form.Get("client_id")) diff --git a/pkg/oidcclient/filesession/filesession_test.go b/pkg/oidcclient/filesession/filesession_test.go index ec9e0dec9..cba09a45c 100644 --- a/pkg/oidcclient/filesession/filesession_test.go +++ b/pkg/oidcclient/filesession/filesession_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package filesession @@ -310,6 +310,7 @@ func TestPutToken(t *testing.T) { Type: "Bearer", Expiry: metav1.NewTime(now.Add(-1 * time.Hour)), }, + //nolint:gosec // not a real credential IDToken: &oidctypes.IDToken{ Token: "old-id-token2", Expiry: metav1.NewTime(now.Add(-1 * time.Hour)), @@ -508,6 +509,7 @@ func (e *errorCollector) require(want []string, subs ...string) { require.Len(e.t, e.saw, len(want)) for i, w := range want { for i := 0; i < len(subs); i += 2 { + //nolint:gosec // these indices will not be out of bounds as long as callers pass the expected number of arguments w = strings.ReplaceAll(w, subs[i], subs[i+1]) } require.EqualError(e.t, e.saw[i], w) diff --git a/pkg/oidcclient/login.go b/pkg/oidcclient/login.go index 2cd8a911a..732ea3e52 100644 --- a/pkg/oidcclient/login.go +++ b/pkg/oidcclient/login.go @@ -76,7 +76,10 @@ const ( ) // stdin returns the file descriptor for stdin as an int. -func stdin() int { return int(os.Stdin.Fd()) } +func stdin() int { + //nolint:gosec // casting like this is the documented way to pass file descriptors to the term package + return int(os.Stdin.Fd()) +} type handlerState struct { // Basic parameters. @@ -1234,7 +1237,7 @@ func (h *handlerState) handleRefresh(ctx context.Context, refreshToken *oidctype // these messages would be the same. Note that using httperr.Wrap will cause the details of the wrapped // err to be printed by the CLI, but not printed in the browser due to the way that the httperr package // works, so avoid using httperr.Wrap in this function. -func (h *handlerState) handleAuthCodeCallback(w http.ResponseWriter, r *http.Request) (returnedErr error) { +func (h *handlerState) handleAuthCodeCallback(w http.ResponseWriter, r *http.Request) (returnedErr error) { //nolint:funlen defer func() { // If we returned an error, then also report it back over the channel to the main CLI goroutine. // Because returnedErr is the named return value, inside this defer returnedErr will hold the value @@ -1286,6 +1289,7 @@ func (h *handlerState) handleAuthCodeCallback(w http.ResponseWriter, r *http.Req return nil // keep listening for more requests case http.MethodPost: + r.Body = http.MaxBytesReader(w, r.Body, 1<<20) // Limit request body size to 1 MB // Parse and pull the response parameters from an application/x-www-form-urlencoded request body. if err = r.ParseForm(); err != nil { // Avoid using httperr.Wrap because that would hide the details of err from the browser output. diff --git a/pkg/oidcclient/login_test.go b/pkg/oidcclient/login_test.go index 8bb1629bc..6aee17244 100644 --- a/pkg/oidcclient/login_test.go +++ b/pkg/oidcclient/login_test.go @@ -1,4 +1,4 @@ -// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package oidcclient @@ -148,6 +148,7 @@ func TestLogin(t *testing.T) { //nolint:gocyclo TokenURL string `json:"token_endpoint"` JWKSURL string `json:"jwks_uri"` } + //nolint:gosec // no credentials here _ = json.NewEncoder(w).Encode(&providerJSON{ Issuer: insecureTokenURLServer.URL, AuthURL: insecureTokenURLServer.URL + "/authorize", @@ -324,6 +325,7 @@ func TestLogin(t *testing.T) { //nolint:gocyclo http.Error(w, "unexpected method", http.StatusMethodNotAllowed) return } + //nolint:gosec // this is a test, so we don't care about limiting request body size if err := r.ParseForm(); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return diff --git a/test/integration/formposthtml_test.go b/test/integration/formposthtml_test.go index 93fc4f4e8..a2d728160 100644 --- a/test/integration/formposthtml_test.go +++ b/test/integration/formposthtml_test.go @@ -1,4 +1,4 @@ -// Copyright 2021-2025 the Pinniped contributors. All Rights Reserved. +// Copyright 2021-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package integration @@ -121,11 +121,13 @@ func formpostCallbackServer(t *testing.T) (string, func(*testing.T, url.Values)) // Allow CORS requests. w.Header().Set("Access-Control-Allow-Origin", "*") + //nolint:gosec // this is a test, so we don't care about limiting request body size assert.NoError(t, r.ParseForm()) // Extract only the POST parameters (r.Form also contains URL query parameters). postParams := url.Values{} for k := range r.Form { + //nolint:gosec // this is a test, so we don't care about limiting request body size if v := r.PostFormValue(k); v != "" { postParams.Set(k, v) } diff --git a/test/integration/leaderelection_test.go b/test/integration/leaderelection_test.go index 6d5a81a7a..52fd0ed31 100644 --- a/test/integration/leaderelection_test.go +++ b/test/integration/leaderelection_test.go @@ -1,4 +1,4 @@ -// Copyright 2021-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2021-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package integration @@ -213,7 +213,7 @@ func waitForIdentity(ctx context.Context, t *testing.T, namespace *corev1.Namesp func runWriteRequest(ctx context.Context, client *kubeclient.Client) error { _, err := client.Kubernetes.AuthenticationV1().TokenReviews().Create(ctx, &authenticationv1.TokenReview{ - Spec: authenticationv1.TokenReviewSpec{Token: "any-non-empty-value"}, + Spec: authenticationv1.TokenReviewSpec{Token: "any-non-empty-value"}, //nolint:gosec // not a real credential }, metav1.CreateOptions{}) return err } diff --git a/test/integration/supervisor_login_test.go b/test/integration/supervisor_login_test.go index b5480cd16..23c071edd 100644 --- a/test/integration/supervisor_login_test.go +++ b/test/integration/supervisor_login_test.go @@ -1815,6 +1815,7 @@ func TestSupervisorLogin_Browser(t *testing.T) { body) }, }, + //nolint:gosec // no credentials here { name: "disallowed requested audience using specific reserved name of a dynamic client on token exchange results in token exchange error", maybeSkip: skipNever, @@ -1835,6 +1836,7 @@ func TestSupervisorLogin_Browser(t *testing.T) { body) }, }, + //nolint:gosec // no credentials here { name: "disallowed requested audience pinniped-cli on token exchange results in token exchange error", maybeSkip: skipNever, @@ -2977,7 +2979,7 @@ func testSupervisorLogin( // Create an HTTP client that can reach the downstream discovery endpoint using the CA certs. httpClient := &http.Client{ Transport: &http.Transport{ - TLSClientConfig: &tls.Config{RootCAs: federationDomainSelfSignedCA.Pool()}, //nolint:gosec // not concerned with TLS MinVersion here + TLSClientConfig: &tls.Config{RootCAs: federationDomainSelfSignedCA.Pool()}, Proxy: func(req *http.Request) (*url.URL, error) { if strings.HasPrefix(req.URL.Host, "127.0.0.1") { // don't proxy requests to localhost to avoid proxying calls to our local callback listener diff --git a/test/testlib/env.go b/test/testlib/env.go index 0c4ea0310..9dc90fa33 100644 --- a/test/testlib/env.go +++ b/test/testlib/env.go @@ -226,6 +226,7 @@ func IntegrationEnv(t *testing.T, opts ...TestEnvOption) *TestEnv { "must specify either PINNIPED_TEST_CLUSTER_CAPABILITY_YAML or PINNIPED_TEST_CLUSTER_CAPABILITY_FILE env var for integration tests", ) if capabilitiesDescriptionYAML == "" { + //nolint:gosec // not concerned with tainted file path input for this test helper bytes, err := os.ReadFile(capabilitiesDescriptionFile) capabilitiesDescriptionYAML = string(bytes) require.NoError(t, err) diff --git a/test/testlib/securetls.go b/test/testlib/securetls.go index 153caaa8e..1f8b073ea 100644 --- a/test/testlib/securetls.go +++ b/test/testlib/securetls.go @@ -1,4 +1,4 @@ -// Copyright 2022-2024 the Pinniped contributors. All Rights Reserved. +// Copyright 2022-2026 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package testlib @@ -83,7 +83,7 @@ func GetExpectedCiphers(config *tls.Config, preference string) string { } else { group = rsa2048 } - s.WriteString(fmt.Sprintf(tls12Item, name, group)) + s.WriteString(fmt.Sprintf(tls12Item, name, group)) //nolint:staticcheck // this is better than fmt.Fprintf because this cannot error if i == len(config.CipherSuites)-1 { break } @@ -96,7 +96,7 @@ func GetExpectedCiphers(config *tls.Config, preference string) string { var s strings.Builder tls13CipherSuites := tlsserver.GetExpectedTLS13Ciphers() for i, id := range tls13CipherSuites { - s.WriteString(fmt.Sprintf(tls13Item, + s.WriteString(fmt.Sprintf(tls13Item, //nolint:staticcheck // this is better than fmt.Fprintf because this cannot error strings.Replace(tls.CipherSuiteName(id), "TLS_", "TLS_AKE_WITH_", 1), tlsserver.GetExpectedTLS13CipherNMapKeyExchangeInfoValue(id)), )