Repository: crossplane/crossplane (go)

Issue:
cossplane cli `--insecure-skip-tls-verify` has no effect for `xpkg push`
<!--
Thank you for helping to improve Crossplane!

Please be sure to search for open issues before raising a new one. We use issues
for bug reports and feature requests. Please find us at https://slack.crossplane.io
for questions, support, and discussion.
-->

### What happened?
For development purposes I want to push a xpkg to a local container registry with self-signed certificate - as [offline installation](https://docs.crossplane.io/latest/concepts/packages/#install-offline) is supported but requires a container registry. While trying to push  the xpkg it doesn't skip tls verification even though it is set in the command.

### How can we reproduce it?
- assume a debian-based system (e.g. ubuntu noble)
- install `ssl-cert`, this will generate snakeoil self-signed certs for this host automatically
- run the registry docker with those certs: `docker run -d --restart=always --name registry -v /etc/ssl:/ssl -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/ssl/certs/ssl-cert-snakeoil.pem -e REGISTRY_HTTP_TLS_KEY=/ssl/private/ssl-cert-snakeoil.key -p 443:443 registry:latest`
- try to push the xpkg: `crossplane xpkg push --insecure-skip-tls-verify -f provider-xyz-v0.0.0-1.g8a91805.xpkg docker-registry-xp.lxd/crossplane/provider-xyz:v0.0.0-1.g8a91805`
- will result into: `crossplane: error: failed to push package file /root/provider-xyz-v0.0.0-1.g8a91805.xpkg: Get "https://docker-registry-xp.lxd/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority`

### What environment did it happen in?
Crossplane version: v1.18.1

"Cloud-Provider": [LXD (VM)](https://canonical.com/lxd)
OS: Ubuntu 24.04.1 LTS
Kernel: Linux docker-registry-xp 6.8.0-49-generic #49-Ubuntu SMP PREEMPT_DYNAMIC Mon Nov  4 02:06:24 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

### Additional information

It is verified that the certificates are loaded correctly and produce the desired output for the container registry:
```
echo | openssl s_client -connect docker-registry-xp.lxd:443 2>/dev/null | openssl x509 -noout -text | grep CN
        Issuer: CN = docker-registry-xp.lxd
        Subject: CN = docker-registry-xp.lxd
```
crossplane cli now only needs to correctly ignore the TLS verification

Note: This issue is independent of the "Cloud Provider" as just raw TLS communication is at fault here. Still included for reference.

Also: Is there a workaround to do the pushing with raw docker commands?

Pull request description:
Honor --insecure-skip-tls-verify flag for crossplane xpkg push command
### Description of your changes

<!--
Briefly describe what this pull request does, and how it is covered by tests.
Be proactive - direct your reviewers' attention to anything that needs special
consideration.

We love pull requests that fix an open issue. If yours does, use the below line
to indicate which issue it fixes, for example "Fixes #500".
-->

Fixes #6156

I have: <!--You MUST either [x] check or [ ] ~strike through~ every item.-->

- [x] Read and followed Crossplane's [contribution process].
- [x] Run `earthly +reviewable` to ensure this PR is ready for review.
- [ ] ~Added or updated unit tests.~
- [ ] ~Added or updated e2e tests.~
- [ ] ~Linked a PR or a [docs tracking issue] to [document this change].~
- [ ] ~Added `backport release-x.y` labels to auto-backport this PR.~
- [ ] ~Followed the [API promotion workflow] if this PR introduces, removes, or promotes an API.~

Need help with this checklist? See the [cheat sheet].

[contribution process]: https://github.com/crossplane/crossplane/tree/main/contributing
[docs tracking issue]: https://github.com/crossplane/docs/issues/new
[document this change]: https://docs.crossplane.io/contribute/contribute
[cheat sheet]: https://github.com/crossplane/crossplane/tree/main/contributing#checklist-cheat-sheet
[API promotion workflow]: https://github.com/crossplane/crossplane/blob/main/contributing/guide-api-promotion.md

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5de3a1013..4063c1c09 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -5,10 +5,6 @@ on:
     branches:
       - main
       - release-*
-      # TODO(negz): Remove this and all references to the v2 branches below
-      # if/when v2 is merged into main. It's a temporary branch for v2 preview
-      # development.
-      - v2 
   pull_request: {}
   workflow_dispatch: {}
 
@@ -356,7 +352,7 @@ jobs:
         run: echo "EARTHLY_MAX_REMOTE_CACHE=true" >> $GITHUB_ENV
 
       - name: Configure Earthly to Push Artifacts
-        if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/v2' || startsWith(github.ref, 'refs/heads/release-')) && env.DOCKER_USR != '' && env.UPBOUND_MARKETPLACE_PUSH_ROBOT_USR != '' && env.AWS_USR != ''
+        if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release-')) && env.DOCKER_USR != '' && env.UPBOUND_MARKETPLACE_PUSH_ROBOT_USR != '' && env.AWS_USR != ''
         run: echo "EARTHLY_PUSH=true" >> $GITHUB_ENV
 
       - name: Set CROSSPLANE_VERSION GitHub Environment Variable
@@ -381,14 +377,6 @@ jobs:
             --secret=AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_PSW }} \
             +ci-promote-build-artifacts --AWS_DEFAULT_REGION=us-east-1 --CROSSPLANE_VERSION=${CROSSPLANE_VERSION} --BUILD_DIR=${GITHUB_REF##*/} --CHANNEL=master
 
-      - name: Push Artifacts to https://releases.crossplane.io/preview/ and https://charts.crossplane.io/preview
-        if: env.AWS_USR != '' && github.ref == 'refs/heads/v2'
-        run: |
-          earthly --strict \
-            --secret=AWS_ACCESS_KEY_ID=${{ secrets.AWS_USR }} \
-            --secret=AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_PSW }} \
-            +ci-promote-build-artifacts --AWS_DEFAULT_REGION=us-east-1 --CROSSPLANE_VERSION=${CROSSPLANE_VERSION} --BUILD_DIR=${GITHUB_REF##*/} --CHANNEL=preview
-
       - name: Upload Artifacts to GitHub
         uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4
         with:
diff --git a/ADOPTERS.md b/ADOPTERS.md
index 97ee42495..3ee70f781 100644
--- a/ADOPTERS.md
+++ b/ADOPTERS.md
@@ -95,4 +95,3 @@ This list is sorted in the order that organizations were added to it.
 | [Jove](https://www.jove.com/) | [@arturkasperek](https://github.com/arturkasperek) | We use Crossplane in production environments to build a Heroku like Internal Developer Platform on top of AWS and AWS EKS. |
 | [Alauda](https://www.alauda.io/) | [@tossmilestone](https://github.com/tossmilestone) | Our container platform product (ACP) uses Crossplane to simplify application deployment and infrastructure provisioning for our clients in production environments. |
 | [Neteera](https://www.neteera.com/) | [@heinanca](https://github.com/heinanca) | We utilize Crossplane to build our EU operations using official and in-house providers. |
-| [Nebinfra](https://www.nebinfra.com) | [@satishweb](https://github.com/satishweb) | Manage multi-cloud digital infrastructure and deliver a self-service framework that empowers engineers to provision application resources for our customers. |
diff --git a/Earthfile b/Earthfile
index c35a30fff..b066f52d4 100644
--- a/Earthfile
+++ b/Earthfile
@@ -3,7 +3,7 @@ VERSION --try --raw-output 0.8
 
 PROJECT crossplane/crossplane
 
-ARG --global GO_VERSION=1.23.7
+ARG --global GO_VERSION=1.23.4
 
 # reviewable checks that a branch is ready for review. Run it before opening a
 # pull request. It will catch a lot of the things our CI workflow will catch.
diff --git a/GOVERNANCE.md b/GOVERNANCE.md
index 864341818..e6d9cac43 100644
--- a/GOVERNANCE.md
+++ b/GOVERNANCE.md
@@ -55,18 +55,20 @@ The following are some guidelines for eligibility to the Steering Committee:
 * There is **no** minimum time period for contributions to the project by the
   proposed member.
 
-### Steering Committee
+### Initial Steering Committee
 
-The members of the steering committee are listed in the table below (listed in
-alphabetical order of first name). When terms of the committee members expire,
-new members will be selected through the [election process](#election-process)
-outlined below.
+The initial steering committee will be nominated by the founders of the project
+in order to ensure continuity of the project charter and vision as additional members come on board.
+Once the terms of the initial committee members expire, new members will be selected through the election
+process outlined below.
+
+Here are the members of the initial steering committee (listed in alphabetical order of first name):
 
 | &nbsp;                                                    | Member                                         | Organization | Email                       | Term Start | Term End   |
 |-----------------------------------------------------------|------------------------------------------------|--------------|-----------------------------|------------|------------|
 | <img width="30px" src="https://github.com/bassam.png">    | [Bassam Tabbara](https://github.com/bassam)    | Upbound      | bassam@upbound.io           | 2024-02-06 | 2026-02-06 |
-| <img width="30px" src="https://github.com/bobh66.png">    | [Bob Haddleton](https://github.com/bobh66)     | Nokia        | bob.haddleton@nokia.com     | 2025-02-06 | 2027-02-06 |
-| <img width="30px" src="https://github.com/lindblombr.png">| [Brian Lindblom](https://github.com/lindblombr)| Apple        | blindblom@apple.com         | 2025-02-06 | 2027-02-06 |
+| <img width="30px" src="https://github.com/lindblombr.png">| [Brian Lindblom](https://github.com/lindblombr)| Apple        | blindblom@apple.com         | 2024-02-06 | 2025-02-07 |
+| <img width="30px" src="https://github.com/bobh66.png">    | [Bob Haddleton](https://github.com/bobh66)     | Nokia        | bob.haddleton@nokia.com     | 2024-02-06 | 2025-02-07 |
 | <img width="30px" src="https://github.com/jbw976.png">    | [Jared Watts](https://github.com/jbw976)       | Upbound      | jared@upbound.io            | 2024-02-06 | 2026-02-06 |
 | <img width="30px" src="https://github.com/negz.png">      | [Nic Cope](https://github.com/negz)            | Upbound      | negz@upbound.io             | 2024-02-06 | 2026-02-06 |
 
diff --git a/cmd/crank/beta/validate/cmd.go b/cmd/crank/beta/validate/cmd.go
index b2c239bfe..0afc7074d 100644
--- a/cmd/crank/beta/validate/cmd.go
+++ b/cmd/crank/beta/validate/cmd.go
@@ -40,12 +40,12 @@ type Cmd struct {
 	Resources  string `arg:"" help:"Resources source which can be a file, directory, or '-' for standard input."`
 
 	// Flags. Keep them in alphabetical order.
-	CacheDir              string `default:"~/.crossplane/cache"                                                       help:"Absolute path to the cache directory where downloaded schemas are stored."`
-	CleanCache            bool   `help:"Clean the cache directory before downloading package schemas."`
-	SkipSuccessResults    bool   `help:"Skip printing success results."`
-	CrossplaneImage       string `help:"Specify the Crossplane image to be used for validating the built-in schemas."`
-	ErrorOnMissingSchemas bool   `default:"false"                                                                     help:"Return non zero exit code if not all schemas are provided."`
-	fs                    afero.Fs
+	CacheDir           string `default:"~/.crossplane/cache"                                                       help:"Absolute path to the cache directory where downloaded schemas are stored."`
+	CleanCache         bool   `help:"Clean the cache directory before downloading package schemas."`
+	SkipSuccessResults bool   `help:"Skip printing success results."`
+	CrossplaneImage    string `help:"Specify the Crossplane image to be used for validating the built-in schemas."`
+
+	fs afero.Fs
 }
 
 // Help prints out the help for the validate command.
@@ -139,7 +139,7 @@ func (c *Cmd) Run(k *kong.Context, _ logging.Logger) error {
 	}
 
 	// Validate resources against schemas
-	if err := SchemaValidation(resources, m.crds, c.ErrorOnMissingSchemas, c.SkipSuccessResults, k.Stdout); err != nil {
+	if err := SchemaValidation(resources, m.crds, c.SkipSuccessResults, k.Stdout); err != nil {
 		return errors.Wrapf(err, "cannot validate resources")
 	}
 
diff --git a/cmd/crank/beta/validate/validate.go b/cmd/crank/beta/validate/validate.go
index 6ee4ee886..7da0f6509 100644
--- a/cmd/crank/beta/validate/validate.go
+++ b/cmd/crank/beta/validate/validate.go
@@ -92,7 +92,7 @@ func newValidatorsAndStructurals(crds []*extv1.CustomResourceDefinition) (map[ru
 }
 
 // SchemaValidation validates the resources against the given CRDs.
-func SchemaValidation(resources []*unstructured.Unstructured, crds []*extv1.CustomResourceDefinition, errorOnMissingSchemas bool, skipSuccessLogs bool, w io.Writer) error { //nolint:gocognit // printing the output increases the cyclomatic complexity a little bit
+func SchemaValidation(resources []*unstructured.Unstructured, crds []*extv1.CustomResourceDefinition, skipSuccessLogs bool, w io.Writer) error { //nolint:gocognit // printing the output increases the cyclomatic complexity a little bit
 	schemaValidators, structurals, err := newValidatorsAndStructurals(crds)
 	if err != nil {
 		return errors.Wrap(err, "cannot create schema validators")
@@ -152,10 +152,6 @@ func SchemaValidation(resources []*unstructured.Unstructured, crds []*extv1.Cust
 		return errors.New("could not validate all resources")
 	}
 
-	if errorOnMissingSchemas && missingSchemas > 0 {
-		return errors.New("could not validate all resources, schema(s) missing")
-	}
-
 	return nil
 }
 
diff --git a/cmd/crank/render/render.go b/cmd/crank/render/render.go
index c922a868d..2069181d1 100644
--- a/cmd/crank/render/render.go
+++ b/cmd/crank/render/render.go
@@ -178,13 +178,8 @@ func Render(ctx context.Context, log logging.Logger, in Inputs) (Outputs, error)
 		return Outputs{}, errors.Wrap(err, "cannot start function runtimes")
 	}
 
-	defer func() { //nolint:contextcheck // See comment on next line.
-		// Don't use the main context, since it may be cancelled by the time we
-		// get to cleanup (e.g., if render times out).
-		stopCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
-		defer cancel()
-
-		if err := runtimes.Stop(stopCtx); err != nil {
+	defer func() {
+		if err := runtimes.Stop(ctx); err != nil {
 			log.Info("Error stopping function runtimes", "error", err)
 		}
 	}()
diff --git a/cmd/crank/render/runtime_docker.go b/cmd/crank/render/runtime_docker.go
index 549cd0f99..64a61ec43 100644
--- a/cmd/crank/render/runtime_docker.go
+++ b/cmd/crank/render/runtime_docker.go
@@ -317,7 +317,7 @@ func (r *RuntimeDocker) getPullOptions() (typesimage.PullOptions, error) {
 	}
 
 	return typesimage.PullOptions{
-		RegistryAuth: base64.StdEncoding.EncodeToString(token),
+		RegistryAuth: base64.URLEncoding.EncodeToString(token),
 	}, nil
 }
 
diff --git a/cmd/crank/xpkg/push.go b/cmd/crank/xpkg/push.go
index 1aceab488..47679ffca 100644
--- a/cmd/crank/xpkg/push.go
+++ b/cmd/crank/xpkg/push.go
@@ -18,7 +18,9 @@ package xpkg
 
 import (
 	"context"
+	"crypto/tls"
 	"fmt"
+	"net/http"
 	"os"
 	"path/filepath"
 
@@ -129,6 +131,17 @@ func (c *pushCmd) Run(logger logging.Logger) error { //nolint:gocognit // This f
 		authn.DefaultKeychain,
 	)
 
+	t := &http.Transport{
+		TLSClientConfig: &tls.Config{
+			InsecureSkipVerify: upCtx.InsecureSkipTLSVerify, //nolint:gosec // we need to support insecure connections if requested
+		},
+	}
+
+	options := []remote.Option{
+		remote.WithAuthFromKeychain(kc),
+		remote.WithTransport(t),
+	}
+
 	// If there's only one package file, handle the simple path.
 	if len(c.PackageFiles) == 1 {
 		img, err := tarball.ImageFromPath(c.PackageFiles[0], nil)
@@ -139,7 +152,7 @@ func (c *pushCmd) Run(logger logging.Logger) error { //nolint:gocognit // This f
 		if err != nil {
 			return errors.Wrapf(err, errAnnotateLayers)
 		}
-		if err := remote.Write(tag, img, remote.WithAuthFromKeychain(kc)); err != nil {
+		if err := remote.Write(tag, img, options...); err != nil {
 			return errors.Wrapf(err, errFmtPushPackage, c.PackageFiles[0])
 		}
 		logger.Debug("Pushed package", "path", c.PackageFiles[0], "ref", tag.String())
@@ -194,7 +207,7 @@ func (c *pushCmd) Run(logger logging.Logger) error { //nolint:gocognit // This f
 					},
 				},
 			}
-			if err := remote.Write(ref, img, remote.WithAuthFromKeychain(kc), remote.WithContext(ctx)); err != nil {
+			if err := remote.Write(ref, img, append(options, remote.WithContext(ctx))...); err != nil {
 				return errors.Wrapf(err, errFmtPushPackage, file)
 			}
 			logger.Debug("Pushed package", "path", file, "ref", ref.String())
@@ -206,7 +219,7 @@ func (c *pushCmd) Run(logger logging.Logger) error { //nolint:gocognit // This f
 		return err
 	}
 
-	if err := remote.WriteIndex(tag, mutate.AppendManifests(empty.Index, adds...), remote.WithAuthFromKeychain(kc)); err != nil {
+	if err := remote.WriteIndex(tag, mutate.AppendManifests(empty.Index, adds...), options...); err != nil {
 		return errors.Wrapf(err, errFmtWriteIndex, len(adds))
 	}
 	logger.Debug("Wrote OCI index", "ref", tag.String(), "manifests", len(adds))
diff --git a/go.mod b/go.mod
index 0cf619488..ae2084579 100644
--- a/go.mod
+++ b/go.mod
@@ -1,8 +1,6 @@
 module github.com/crossplane/crossplane
 
-go 1.23.0
-
-toolchain go1.23.7
+go 1.22.8
 
 require (
 	dario.cat/mergo v1.0.1
@@ -15,7 +13,7 @@ require (
 	github.com/emicklei/dot v1.6.2
 	github.com/go-git/go-billy/v5 v5.6.0
 	github.com/go-git/go-git/v5 v5.13.0
-	github.com/golang-jwt/jwt/v5 v5.2.2
+	github.com/golang-jwt/jwt/v5 v5.2.1
 	github.com/google/go-cmp v0.6.0
 	github.com/google/go-containerregistry v0.19.2
 	github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20230919002926-dbcd01c402b2
@@ -27,7 +25,7 @@ require (
 	github.com/sirupsen/logrus v1.9.3
 	github.com/spf13/afero v1.11.0
 	github.com/upbound/up-sdk-go v0.1.1-0.20240122203953-2d00664aab8e
-	golang.org/x/sync v0.11.0
+	golang.org/x/sync v0.10.0
 	google.golang.org/grpc v1.68.0
 	google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0
 	google.golang.org/protobuf v1.35.2
@@ -74,7 +72,7 @@ require (
 	github.com/go-chi/chi v4.1.2+incompatible // indirect
 	github.com/go-errors/errors v1.4.2 // indirect
 	github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
-	github.com/go-jose/go-jose/v4 v4.0.5 // indirect
+	github.com/go-jose/go-jose/v4 v4.0.2 // indirect
 	github.com/go-openapi/analysis v0.23.0 // indirect
 	github.com/go-openapi/errors v0.22.0 // indirect
 	github.com/go-openapi/loads v0.22.0 // indirect
@@ -82,7 +80,7 @@ require (
 	github.com/go-openapi/spec v0.21.0 // indirect
 	github.com/go-openapi/strfmt v0.23.0 // indirect
 	github.com/go-openapi/validate v0.24.0 // indirect
-	github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
+	github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
 	github.com/golang/snappy v0.0.4 // indirect
 	github.com/google/btree v1.1.2 // indirect
 	github.com/google/cel-go v0.20.1 // indirect
@@ -244,13 +242,13 @@ require (
 	go.opentelemetry.io/otel/trace v1.33.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
-	golang.org/x/crypto v0.35.0 // indirect
+	golang.org/x/crypto v0.31.0 // indirect
 	golang.org/x/mod v0.21.0 // indirect
-	golang.org/x/net v0.36.0
-	golang.org/x/oauth2 v0.27.0 // indirect
-	golang.org/x/sys v0.30.0 // indirect
-	golang.org/x/term v0.29.0
-	golang.org/x/text v0.22.0 // indirect
+	golang.org/x/net v0.33.0
+	golang.org/x/oauth2 v0.24.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
+	golang.org/x/term v0.27.0
+	golang.org/x/text v0.21.0 // indirect
 	golang.org/x/time v0.6.0 // indirect
 	golang.org/x/tools v0.26.0 // indirect
 	gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
diff --git a/go.sum b/go.sum
index 674090a98..857095ff8 100644
--- a/go.sum
+++ b/go.sum
@@ -303,8 +303,8 @@ github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
 github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
 github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
 github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
-github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
-github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
+github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk=
+github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
 github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -351,10 +351,10 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
 github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
-github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
-github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
-github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
-github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
+github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
+github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
+github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -784,8 +784,8 @@ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0
 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
-golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
-golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
 golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
@@ -818,11 +818,11 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
-golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
+golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
+golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
-golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
+golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
+golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -831,8 +831,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
-golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -861,23 +861,23 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
-golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
-golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
-golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
 golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=


Test patch:
diff --git a/cmd/crank/beta/validate/validate_test.go b/cmd/crank/beta/validate/validate_test.go
index db08bc708..5524bbe68 100644
--- a/cmd/crank/beta/validate/validate_test.go
+++ b/cmd/crank/beta/validate/validate_test.go
@@ -1183,9 +1183,8 @@ func TestConvertToCRDs(t *testing.T) {
 
 func TestValidateResources(t *testing.T) {
 	type args struct {
-		resources             []*unstructured.Unstructured
-		crds                  []*extv1.CustomResourceDefinition
-		errorOnMissingSchemas bool
+		resources []*unstructured.Unstructured
+		crds      []*extv1.CustomResourceDefinition
 	}
 	type want struct {
 		err error
@@ -1241,53 +1240,6 @@ func TestValidateResources(t *testing.T) {
 				},
 			},
 		},
-		"ValidWithMissingSchemasEnabled": {
-			reason: "Should not return an error if the resources are valid and schemas are not missing",
-			args: args{
-				resources: []*unstructured.Unstructured{
-					{
-						Object: map[string]interface{}{
-							"apiVersion": "test.org/v1alpha1",
-							"kind":       "Test",
-							"metadata": map[string]interface{}{
-								"name": "test",
-							},
-							"spec": map[string]interface{}{
-								"replicas": 1,
-							},
-						},
-					},
-				},
-				crds: []*extv1.CustomResourceDefinition{
-					testCRD,
-				},
-				errorOnMissingSchemas: true,
-			},
-		},
-		"ErrorOnMissingSchemas": {
-			reason: "Should return an error if schemas are missing",
-			args: args{
-				resources: []*unstructured.Unstructured{
-					{
-						Object: map[string]interface{}{
-							"apiVersion": "test.org/v1alpha1",
-							"kind":       "Test",
-							"metadata": map[string]interface{}{
-								"name": "test",
-							},
-							"spec": map[string]interface{}{
-								"replicas": 1,
-							},
-						},
-					},
-				},
-				crds:                  []*extv1.CustomResourceDefinition{},
-				errorOnMissingSchemas: true,
-			},
-			want: want{
-				err: errors.New("could not validate all resources, schema(s) missing"),
-			},
-		},
 		"Invalid": {
 			reason: "Should return an error if the resources are invalid",
 			args: args{
@@ -1364,7 +1316,7 @@ func TestValidateResources(t *testing.T) {
 	for name, tc := range cases {
 		t.Run(name, func(t *testing.T) {
 			w := &bytes.Buffer{}
-			got := SchemaValidation(tc.args.resources, tc.args.crds, tc.args.errorOnMissingSchemas, false, w)
+			got := SchemaValidation(tc.args.resources, tc.args.crds, false, w)
 
 			if diff := cmp.Diff(tc.want.err, got, test.EquateErrors()); diff != "" {
 				t.Errorf("%s\nvalidateResources(...): -want error, +got error:\n%s", tc.reason, diff)