cloudfoundry / cloudfoundry/cli
SermoDigital/jose panics at init under Go 1.27, breaking any binary that links the CLI
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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