File fix-CVE-2025-47913-ssh-agent.patch of Package act.19244
##
# PATCH-PURPOSE: Prevent panic in vendored golang.org/x/crypto ssh/agent client
# when receiving unexpected message types for key listing or
# signing operations AND introduce regression tests verifying
# error behavior (no panic) for List() and SignWithFlags().
# PATCH-STATUS: Upstream functional change merged (Go crypto CL 700295); test added here
# for downstream regression coverage (original snapshot lacked it).
# PATCH-ORIGIN: https://go-review.googlesource.com/c/crypto/+/700295 (logic) + downstream test.
# PATCH-AUTHOR: Maintainer <elimat@opensuse.org>
# PATCH-DATE: 2025-11-16
# PATCH-REFERENCE: bsc#1253608 CVE-2025-47913
# PATCH-FEATURE: security hardening + regression test
# DESCRIPTION: Replace unreachable panic paths in List() and SignWithFlags() with
# default switch branches returning an error identifying the
# unexpected agent response type; add client_test.go to assert
# errors on unexpected SUCCESS responses.
# NOTES: Test mirrors local harness behavior; imports adjusted for vendored tree.
##
--- vendor_orig/vendor/golang.org/x/crypto/ssh/agent/client.go 2023-05-10 09:34:39.000000000 +0200
+++ vendor/golang.org/x/crypto/ssh/agent/client.go 2025-11-16 22:18:27.410479142 +0100
@@ -425,8 +425,9 @@
return keys, nil
case *failureAgentMsg:
return nil, errors.New("agent: failed to list keys")
+ default:
+ return nil, fmt.Errorf("agent: unexpected response type %T", msg)
}
- panic("unreachable")
}
// Sign has the agent sign the data using a protocol 2 key as defined
@@ -457,8 +458,9 @@
return &sig, nil
case *failureAgentMsg:
return nil, errors.New("agent: failed to sign challenge")
+ default:
+ return nil, fmt.Errorf("agent: unexpected response type %T", msg)
}
- panic("unreachable")
}
// unmarshal parses an agent message in packet, returning the parsed
--- /dev/null 2025-11-16 00:00:00.000000000 +0000
+++ vendor/golang.org/x/crypto/ssh/agent/client_test.go 2025-11-16 00:00:00.000000000 +0000
@@ -0,0 +1,73 @@
+package agent
+
+import (
+ "crypto/rand"
+ "crypto/rsa"
+ "io"
+ "net"
+ "testing"
+ "time"
+
+ "golang.org/x/crypto/ssh"
+)
+
+// fakeConn implements net.Conn minimally for crafting agent replies.
+type fakeConn struct {
+ buf []byte
+}
+
+func (f *fakeConn) Read(b []byte) (int, error) {
+ if len(f.buf) == 0 {
+ return 0, io.EOF
+ }
+ n := copy(b, f.buf)
+ f.buf = f.buf[n:]
+ return n, nil
+}
+func (f *fakeConn) Write(b []byte) (int, error) { return len(b), nil }
+func (f *fakeConn) Close() error { return nil }
+func (f *fakeConn) LocalAddr() net.Addr { return nil }
+func (f *fakeConn) RemoteAddr() net.Addr { return nil }
+func (f *fakeConn) SetDeadline(t time.Time) error { return nil }
+func (f *fakeConn) SetReadDeadline(t time.Time) error { return nil }
+func (f *fakeConn) SetWriteDeadline(t time.Time) error { return nil }
+
+// marshalPacket builds an ssh-agent length-prefixed packet from payload.
+func marshalPacket(payload []byte) []byte {
+ l := len(payload)
+ return append([]byte{byte(l >> 24), byte(l >> 16), byte(l >> 8), byte(l)}, payload...)
+}
+
+// unexpectedSuccess constructs a SUCCESS message which is invalid in the contexts tested.
+func unexpectedSuccess() []byte {
+ return []byte{agentSuccess}
+}
+
+func TestListUnexpectedMessageType(t *testing.T) {
+ // Craft packet: key listing request expects identitiesAnswerAgentMsg, not SUCCESS.
+ pkt := marshalPacket(unexpectedSuccess())
+ c := &client{conn: &fakeConn{buf: pkt}}
+ keys, err := c.List()
+ if err == nil {
+ t.Fatalf("expected error for unexpected response, got nil and %d keys", len(keys))
+ }
+}
+
+func TestSignUnexpectedMessageType(t *testing.T) {
+ // Sign request expects signResponseAgentMsg, not SUCCESS.
+ pkt := marshalPacket(unexpectedSuccess())
+ c := &client{conn: &fakeConn{buf: pkt}}
+ // Use a real RSA key for proper ssh.PublicKey interface.
+ privKey, err := rsa.GenerateKey(rand.Reader, 2048)
+ if err != nil {
+ t.Fatal(err)
+ }
+ pubKey, err := ssh.NewPublicKey(&privKey.PublicKey)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = c.SignWithFlags(pubKey, []byte("data"), 0)
+ if err == nil {
+ t.Fatalf("expected error for unexpected response in SignWithFlags, got nil")
+ }
+}