cloudfoundry / cloudfoundry/cli

SermoDigital/jose panics at init under Go 1.27, breaking any binary that links the CLI

Open
#3,851 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
1.9k
Forks
990
Avg merge
1d 7h
Merged PRs (30d)
8

Description

Summary

github.com/SermoDigital/jose registers a hash function against id 0 from
an init function. Go 1.27 rejects that outright, so the panic fires before
main and every binary linking the package crash-loops on startup.

The library is unmaintained — no upstream push since October 2019 — so this
will not be fixed at the source.

The breakage

crypto/none.go registers the "none" algorithm against hash id 0:

func init() {
	crypto.RegisterHash(crypto.Hash(0), h)
}

Through Go 1.26, RegisterHash only rejected ids at or above maxHash:

// go1.26
func RegisterHash(h Hash, f func() hash.Hash) {
	if h >= maxHash {
		panic("crypto: RegisterHash of unknown hash function")
	}
	hashes[h] = f
}

Go 1.27 added an explicit zero check:

// go1.27
func RegisterHash(h Hash, f func() hash.Hash) {
	if h == 0 || h >= maxHash {
		panic("crypto: RegisterHash of unknown hash function")
	}
	...
}

The resulting failure, before any application code runs:

panic: crypto: RegisterHash of unknown hash function

goroutine 1 [running]:
crypto.RegisterHash(...)
	/usr/local/go/src/crypto/crypto.go:158
github.com/SermoDigital/jose/crypto.init.0()
	.../SermoDigital/jose@v0.9.2-0.20161205224733-f6df55f235c2/crypto/none.go:11
Why this may be more urgent than it looks

This is not gated on the CLI itself moving to Go 1.27. The go directive
sets a language version, not the toolchain that gets linked, and a
toolchain line only sets a minimum — a newer local toolchain still
satisfies it and is what gets used. So the panic depends purely on the Go
version of whoever is building.

That includes projects importing the CLI as a library. Stratos embeds
actor/v7action and actor/v7pushaction to implement cf push, and as of
Go 1.27 cannot produce a working binary at all. The build succeeds — the
failure only shows up at startup, which makes it easy to ship unknowingly.

Scope of a fix

The dependency is used in 9 non-test files, through 4 symbols:

Symbol Uses
jws.ParseJWT 8
jwt.JWT 14
jws.NewJWT 2
jws.Claims 2

Mostly reading claims out of UAA tokens — util/configv3/default_user_config.go,
actor/v7action/token.go, api/cloudcontroller/wrapper/uaa_authentication.go,
cf/api/authentication/authentication.go.

One wrinkle: jwt.JWT appears in command/v7/actor.go, so it is part of the
Actor interface and the counterfeiter fakes would need regenerating. Not a
pure leaf swap.

github.com/go-jose/go-jose/v4 is actively maintained and covers this usage,
but the CLI has no JWT library in go.mod today apart from this one, so the
choice is yours rather than something a drive-by PR should decide. Happy to
put up the PR once you indicate a preferred library.

For context, #1814 and #1892 show this dependency has been awkward before,
for unrelated reasons.

Workaround in the meantime

Consumers can point a replace at a fork with the registration removed.
Dropping it is safe: "none" is installed into the jws signing-method map
by a map literal rather than RegisterSigningMethod, nothing else calls
Available() on it, and SigningMethodNone.Sign/Verify are no-ops that
never construct the hash. The only behavioural change is that
Unsecured.Hasher().Available() reports false.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with go.mod and the nine non-test files using SermoDigital/jose, especially util/configv3/default_user_config.go, actor/v7action/token.go, api/cloudcontroller/wrapper/uaa_authentication.go, cf/api/authentication/authentication.go, and command/v7/actor.go. Compare the required symbols with github.com/go-jose/go-jose/v4 and account for the Actor interface and counterfeiter fakes. Done means the dependency choice is settled, the usages and generated fakes are updated, and startup works with Go 1.27.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
cli
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.