CVE-2024-45337
Critical · 9.1CVSS
9.1
EPSS
3.2%
Published
Dec 12, 2024
CISA due date
—
Cloudanix analysis
Some SSH server programs built with Go could accidentally give access to the wrong users because they trust the wrong information about which key was actually used to log in.
- Exploitation
- Remote Unauthenticated
- Attacker needs
- None
- Complexity
- Low
- Impact
- Full Compromise
- Component
- Library
- Class
- Authorization Bypass
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
Applications misusing ServerConfig.PublicKeyCallback may authorize connections based on a key that was offered but not used for authentication, allowing an attacker to supply multiple keys and authenticate with one while the callback state reflects another.
Why it matters to the business
Organizations running Go-based SSH servers risk unauthorized access to systems and data if custom authorization logic relies on callback order or stored keys instead of the official Permissions.Extensions mechanism; prevalence of golang/crypto increases exposure across many applications.
How an attack unfolds
An attacker connects to an affected SSH server, supplies multiple public keys in sequence to trigger repeated PublicKeyCallback invocations, then completes authentication with a key they control; vulnerable applications that record the final callback key for later authorization decisions incorrectly associate privileges with an uncontrolled key.
How to fix it
Upgrade golang.org/x/crypto to commit b4f1988a35dee11ec3e05d6bf3e90b695fbd8909 or later; refactor code to store authentication data exclusively in the Permissions.Extensions field returned by authentication callbacks and retrieve it via ServerConn.Permissions after connection establishment; avoid sharing Permissions objects across attempts.
How to confirm the fix worked
Confirm golang.org/x/crypto version is at or above the fixed commit; test SSH servers by sending multiple keys followed by authentication and verify that only the actual authenticating key influences authorization decisions.
Typical attack path
- Initiate SSH connection and send multiple public keys to invoke PublicKeyCallback repeatedly
- Complete authentication using a controlled private key while the final callback reflects an uncontrolled key
- Exploit application logic that derives authorization from the last observed callback key or stored state
How to detect it
Review SSH server logs for connections that present multiple public keys before successful authentication; inspect application logs or audit trails for authorization decisions made immediately after PublicKeyCallback invocations; correlate with source code paths that store keys outside Permissions.Extensions.
What your security team should do
- Prioritize upgrade of golang.org/x/crypto to the fixed commit across all affected services
- Audit all code and third-party libraries that implement or wrap PublicKeyCallback for reliance on callback ordering or external state
- Migrate authorization logic to use Permissions.Extensions before connection establishment completes
- Monitor dependency graphs for downstream projects that consume vulnerable golang/crypto versions
The record
Applications and libraries which misuse connection.serverAuthenticate (via callback field ServerConfig.PublicKeyCallback) may be susceptible to an authorization bypass. The documentation for ServerConfig.PublicKeyCallback says that "A call to this function does not guarantee that the key offered is in fact used to authenticate." Specifically, the SSH protocol allows clients to inquire about whether a public key is acceptable before proving control of the corresponding private key. PublicKeyCallback may be called with multiple keys, and the order in which the keys were provided cannot be used to infer which key the client successfully authenticated with, if any. Some applications, which store the key(s) passed to PublicKeyCallback (or derived information) and make security relevant determinations based on it once the connection is established, may make incorrect assumptions. For example, an attacker may send public keys A and B, and then authenticate with A. PublicKeyCallback would be called only twice, first with A and then with B. A vulnerable application may then make authorization decisions based on key B for which the attacker does not actually control the private key. Since this API is widely misused, as a partial mitigation golang.org/x/cry...@v0.31.0 enforces the property that, when successfully authenticating via public key, the last key passed to ServerConfig.PublicKeyCallback will be the key used to authenticate the connection. PublicKeyCallback will now be called multiple times with the same key, if necessary. Note that the client may still not control the last key passed to PublicKeyCallback if the connection is then authenticated with a different method, such as PasswordCallback, KeyboardInteractiveCallback, or NoClientAuth. Users should be using the Extensions field of the Permissions return value from the various authentication callbacks to record data associated with the authentication attempt instead of referencing external state. Once the connection is established the state corresponding to the successful authentication attempt can be retrieved via the ServerConn.Permissions field. Note that some third-party libraries misuse the Permissions type by sharing it across authentication attempts; users of third-party libraries should refer to the relevant projects for guidance.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| Go | golang.org/x/crypto | 0 | 0.31.0 |
| Chainguard | aactl | 0 | 0.4.12-r20 |
| Chainguard | actions-runner-controller | 0 | 0.9.3-r4 |
| Chainguard | actions-runner-controller-compat | 0 | 0.9.3-r4 |
| Chainguard | actions-runner-controller-fips | 0 | 0.9.3-r4 |
| Chainguard | actions-runner-controller-fips-compat | 0 | 0.9.3-r4 |
| Chainguard | age | 0 | 1.2.0-r3 |
| Chainguard | age-fips | 0 | 1.2.0-r1 |
| Chainguard | amass | 0 | 4.2.0-r14 |
| Chainguard | amazon-cloudwatch-agent | 0 | 1.300051.0-r1 |
| Chainguard | amazon-cloudwatch-agent-all | 0 | 1.300051.0-r1 |
| Chainguard | amazon-cloudwatch-agent-amazon-cloudwatch-agent-config-wizard | 0 | 1.300051.0-r1 |
| Chainguard | amazon-cloudwatch-agent-amazon-cloudwatch-agent-config-wizard-fips | 0 | 1.300050.0-r2 |
| Chainguard | amazon-cloudwatch-agent-compat | 0 | 1.300051.0-r1 |
| Chainguard | amazon-cloudwatch-agent-config-downloader | 0 | 1.300051.0-r1 |
| Chainguard | amazon-cloudwatch-agent-config-downloader-fips | 0 | 1.300050.0-r2 |
| Chainguard | amazon-cloudwatch-agent-config-translator | 0 | 1.300051.0-r1 |
| Chainguard | amazon-cloudwatch-agent-config-translator-fips | 0 | 1.300050.0-r2 |
| Chainguard | amazon-cloudwatch-agent-fips | 0 | 1.300050.0-r2 |
| Chainguard | amazon-cloudwatch-agent-operator | 0 | 2.0.0-r1 |
| Chainguard | amazon-cloudwatch-agent-operator-compat | 0 | 2.0.0-r1 |
| Chainguard | amazon-cloudwatch-agent-operator-fips | 0 | 2.0.0-r1 |
| Chainguard | amazon-cloudwatch-agent-operator-fips-compat | 0 | 2.0.0-r1 |
| Chainguard | amazon-cloudwatch-agent-start-amazon-cloudwatch-agent | 0 | 1.300051.0-r1 |
| Chainguard | amazon-cloudwatch-agent-start-amazon-cloudwatch-agent-fips | 0 | 1.300050.0-r2 |
| Chainguard | amazon-ssm-agent | 0 | 3.3.1957.0-r5 |
| Chainguard | amazon-ssm-agent-ecs-exec | 0 | 3.3.1957.0-r5 |
| Chainguard | apko | 0 | 0.21.0-r1 |
| Chainguard | argo-cd-2.10 | 0 | 2.10.18-r2 |
| Chainguard | argo-cd-2.10-compat | 0 | 2.10.18-r2 |
| Chainguard | argo-cd-2.10-repo-server | 0 | 2.10.18-r2 |
| Chainguard | argo-cd-2.11 | 0 | 2.11.12-r1 |
| Chainguard | argo-cd-2.11-compat | 0 | 2.11.12-r1 |
| Chainguard | argo-cd-2.11-repo-server | 0 | 2.11.12-r1 |
| Chainguard | argo-cd-2.12 | 0 | 2.12.8-r1 |
| Chainguard | argo-cd-2.12-compat | 0 | 2.12.8-r1 |
| Chainguard | argo-cd-2.12-repo-server | 0 | 2.12.8-r1 |
| Chainguard | argo-cd-2.13 | 0 | 2.13.2-r1 |
| Chainguard | argo-cd-2.13-compat | 0 | 2.13.2-r1 |
| Chainguard | argo-cd-2.13-repo-server | 0 | 2.13.2-r1 |
| Chainguard | argo-cd-fips-2.10 | 0 | 2.10.18-r2 |
| Chainguard | argo-cd-fips-2.10-compat | 0 | 2.10.18-r2 |
| Chainguard | argo-cd-fips-2.10-repo-server | 0 | 2.10.18-r2 |
| Chainguard | argo-cd-fips-2.11 | 0 | 2.11.12-r1 |
| Chainguard | argo-cd-fips-2.11-compat | 0 | 2.11.12-r1 |
| Chainguard | argo-cd-fips-2.11-repo-server | 0 | 2.11.12-r1 |
| Chainguard | argo-cd-fips-2.12 | 0 | 2.12.8-r1 |
| Chainguard | argo-cd-fips-2.12-compat | 0 | 2.12.8-r1 |
| Chainguard | argo-cd-fips-2.12-repo-server | 0 | 2.12.8-r1 |
| Chainguard | argo-cd-fips-2.13 | 0 | 2.13.2-r1 |
| Chainguard | argo-cd-fips-2.13-compat | 0 | 2.13.2-r1 |
| Chainguard | argo-cd-fips-2.13-repo-server | 0 | 2.13.2-r1 |
| Chainguard | argo-events | 0 | 1.9.3-r1 |
| Chainguard | argo-events-compat | 0 | 1.9.3-r1 |
| Chainguard | argo-events-fips | 0 | 1.9.3-r1 |
| Chainguard | argo-events-fips-compat | 0 | 1.9.3-r1 |
| Chainguard | argo-rollouts | 0 | 1.7.2-r2 |
| Chainguard | argo-rollouts-compat | 0 | 1.7.2-r2 |
| Chainguard | argo-rollouts-fips | 0 | 1.7.2-r2 |
| Chainguard | argo-workflow-cli | 0 | 3.6.2-r1 |
| Chainguard | argo-workflow-cli-fips | 0 | 3.6.2-r1 |
| Chainguard | argo-workflow-controller | 0 | 3.6.2-r1 |
| Chainguard | argo-workflow-controller-compat | 0 | 3.6.2-r1 |
| Chainguard | argo-workflow-controller-compat-fips | 0 | 3.6.2-r1 |
| Chainguard | argo-workflow-controller-fips | 0 | 3.6.2-r1 |
| Chainguard | argo-workflow-executor | 0 | 3.6.2-r1 |
| Chainguard | argo-workflow-executor-compat | 0 | 3.6.2-r1 |
| Chainguard | argo-workflow-executor-compat-fips | 0 | 3.6.2-r1 |
| Chainguard | argo-workflow-executor-fips | 0 | 3.6.2-r1 |
| Chainguard | argo-workflows | 0 | 3.6.2-r1 |
| Chainguard | argo-workflows-fips | 0 | 3.6.2-r1 |
| Chainguard | argo-workflows-known-hosts | 0 | 3.6.2-r1 |
| Chainguard | argo-workflows-known-hosts-fips | 0 | 3.6.2-r1 |
| Chainguard | argo-workflows-ui | 0 | 3.6.2-r1 |
| Chainguard | atlantis | 0 | 0.31.0-r1 |
| Chainguard | atlantis-fips | 0 | 0.31.0-r1 |
| Chainguard | auditbeat-7 | 0 | 7.17.26-r1 |
| Chainguard | auditbeat-7-oci-entrypoint | 0 | 7.17.26-r1 |
| Chainguard | auditbeat-8 | 0 | 8.16.1-r1 |
| Chainguard | auditbeat-8-oci-entrypoint | 0 | 8.16.1-r1 |
| Chainguard | auditbeat-fips-7 | 0 | 7.17.26-r1 |
| Chainguard | auditbeat-fips-8 | 0 | 8.16.1-r1 |
| Chainguard | authservice | 0 | 1.0.3-r1 |
| Chainguard | authservice-compat | 0 | 1.0.3-r1 |
| Chainguard | authservice-fips | 0 | 1.0.3-r1 |
| Chainguard | authservice-fips-compat | 0 | 1.0.3-r1 |
| Chainguard | azcopy | 0 | 10.27.1-r1 |
| Chainguard | azcopy-fips | 0 | 10.27.1-r1 |
| Chainguard | azure-aad-pod-identity-mic | 0 | 1.8.17-r14 |
| Chainguard | azure-aad-pod-identity-nmi | 0 | 1.8.17-r14 |
| Chainguard | azuredisk-csi-1.28 | 0 | 1.28.11-r4 |
| Chainguard | azuredisk-csi-1.28-compat | 0 | 1.28.11-r4 |
| Chainguard | azuredisk-csi-1.29 | 0 | 1.29.11-r1 |
| Chainguard | azuredisk-csi-1.29-compat | 0 | 1.29.11-r1 |
| Chainguard | azuredisk-csi-1.30 | 0 | 1.30.6-r1 |
| Chainguard | azuredisk-csi-1.30-compat | 0 | 1.30.6-r1 |
| Chainguard | azuredisk-csi-1.31 | 0 | 1.31.1-r1 |
| Chainguard | azuredisk-csi-1.31-compat | 0 | 1.31.1-r1 |
| Chainguard | azuredisk-csi-fips-1.28 | 0 | 1.28.11-r3 |
| Chainguard | azuredisk-csi-fips-1.29 | 0 | 1.29.11-r1 |
| Chainguard | azuredisk-csi-fips-1.30 | 0 | 1.30.6-r1 |
| Chainguard | azuredisk-csi-fips-1.31 | 0 | 1.31.1-r1 |
| Chainguard | bank-vaults | 0 | 1.20.4-r21 |
| Chainguard | bank-vaults-fips | 0 | 1.20.4-r17 |
| Chainguard | bank-vaults-template | 0 | 1.20.4-r21 |
| Chainguard | bank-vaults-template-fips | 0 | 1.20.4-r17 |
| Chainguard | beats-7 | 0 | 7.17.26-r1 |
| Chainguard | beats-8 | 0 | 8.16.1-r1 |
| Chainguard | beats-fips-7 | 0 | 7.17.26-r1 |
| Chainguard | beats-fips-8 | 0 | 8.16.1-r1 |
| Chainguard | bom | 0 | 0.6.0-r11 |
| Chainguard | boring-registry | 0 | 0.15.4-r2 |
| Chainguard | boring-registry-fips | 0 | 0.15.4-r2 |
| Chainguard | buf | 0 | 1.47.2-r2 |
| Chainguard | buildah | 0 | 1.38.0-r1 |
| Chainguard | buildctl | 0 | 0.18.1-r2 |
| Chainguard | buildctl-fips | 0 | 0.18.1-r1 |
| Chainguard | buildkitd | 0 | 0.18.1-r2 |
| Chainguard | buildkitd-fips | 0 | 0.18.1-r1 |
| Chainguard | caddy | 0 | 2.8.4-r5 |
| Chainguard | caddy-fips | 0 | 2.8.4-r5 |
| Chainguard | caddy-man | 0 | 2.8.4-r5 |
| Chainguard | caddy-src | 0 | 2.8.4-r5 |
| Chainguard | cadvisor | 0 | 0.51.0-r1 |
| Chainguard | cadvisor-compat | 0 | 0.51.0-r1 |
| Chainguard | cadvisor-fips | 0 | 0.50.0-r3 |
| Chainguard | calico-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-3.27-apiserver | 0 | 3.27.5-r1 |
| Chainguard | calico-3.27-app-policy | 0 | 3.27.5-r1 |
| Chainguard | calico-3.27-calicoctl | 0 | 3.27.5-r1 |
| Chainguard | calico-3.27-cni | 0 | 3.27.5-r1 |
| Chainguard | calico-3.27-cni-compat | 0 | 3.27.5-r1 |
| Chainguard | calico-3.27-felix | 0 | 3.27.5-r1 |
| Chainguard | calico-3.27-kube-controllers | 0 | 3.27.5-r1 |
| Chainguard | calico-3.27-node | 0 | 3.27.5-r1 |
| Chainguard | calico-3.27-pod2daemon | 0 | 3.27.5-r1 |
| Chainguard | calico-3.27-pod2daemon-flexvol-compat | 0 | 3.27.5-r1 |
| Chainguard | calico-3.27-typha-client | 0 | 3.27.5-r1 |
| Chainguard | calico-3.27-typhad | 0 | 3.27.5-r1 |
| Chainguard | calico-3.28 | 0 | 3.28.2-r3 |
| Chainguard | calico-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-apiserver-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-apiserver-3.28 | 0 | 3.28.2-r3 |
| Chainguard | calico-apiserver-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-apiserver-compat-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-apiserver-compat-3.28 | 0 | 3.28.2-r3 |
| Chainguard | calico-apiserver-compat-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-apiserver-compat-fips-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-apiserver-fips-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-apiserver-fips-3.28 | 0 | 3.28.2-r1 |
| Chainguard | calico-apiserver-fips-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-app-policy-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-app-policy-3.28 | 0 | 3.28.2-r3 |
| Chainguard | calico-app-policy-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-app-policy-fips-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-app-policy-fips-3.28 | 0 | 3.28.2-r1 |
| Chainguard | calico-app-policy-fips-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-cni-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-cni-3.28 | 0 | 3.28.2-r3 |
| Chainguard | calico-cni-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-cni-compat-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-cni-compat-3.28 | 0 | 3.28.2-r3 |
| Chainguard | calico-cni-compat-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-cni-compat-fips-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-cni-compat-fips-3.28 | 0 | 3.28.2-r1 |
| Chainguard | calico-cni-compat-fips-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-cni-fips-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-cni-fips-3.28 | 0 | 3.28.2-r1 |
| Chainguard | calico-cni-fips-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-felix-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-felix-3.28 | 0 | 3.28.2-r3 |
| Chainguard | calico-felix-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-felix-fips-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-felix-fips-3.28 | 0 | 3.28.2-r1 |
| Chainguard | calico-felix-fips-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-fips-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-fips-3.28 | 0 | 3.28.2-r1 |
| Chainguard | calico-fips-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-key-cert-provisioner-3.28 | 0 | 3.28.2-r3 |
| Chainguard | calico-key-cert-provisioner-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-key-cert-provisioner-fips-3.28 | 0 | 3.28.2-r1 |
| Chainguard | calico-key-cert-provisioner-fips-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-kube-controllers-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-kube-controllers-3.28 | 0 | 3.28.2-r3 |
| Chainguard | calico-kube-controllers-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-kube-controllers-fips-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-kube-controllers-fips-3.28 | 0 | 3.28.2-r1 |
| Chainguard | calico-kube-controllers-fips-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-node-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-node-3.28 | 0 | 3.28.2-r3 |
| Chainguard | calico-node-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-node-fips-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-node-fips-3.28 | 0 | 3.28.2-r1 |
| Chainguard | calico-node-fips-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-pod2daemon-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-pod2daemon-3.28 | 0 | 3.28.2-r3 |
| Chainguard | calico-pod2daemon-3.29 | 0 | 3.29.1-r1 |
| Chainguard | calico-pod2daemon-fips-3.27 | 0 | 3.27.5-r1 |
| Chainguard | calico-pod2daemon-fips-3.28 | 0 | 3.28.2-r1 |
| Chainguard | calico-pod2daemon-fips-3.29 | 0 | 3.29.1-r1 |
Related vulnerabilities
- CVE-2025-47914 golang.org/x/crypto/ssh/agent vulnerable to panic if message is malformed due to out of… Also affects golang.org/x/crypto
- CVE-2025-58181 golang.org/x/crypto/ssh allows an attacker to cause unbounded memory consumption Also affects golang.org/x/crypto
- CVE-2025-47913 SSH clients receiving SSH_AGENT_SUCCESS when expecting a typed response will panic and… Also affects golang.org/x/crypto
- CVE-2023-48795 The SSH transport protocol with certain OpenSSH extensions, found in OpenSSH before 9.6… Also affects golang.org/x/crypto
- CVE-2021-43565 The x/crypto/ssh package before 0.0.0-20211202192323-5770296d904e of golang.org/x/crypto… Also affects golang.org/x/crypto
- CVE-2022-27191 The golang.org/x/crypto/ssh package before 0.0.0-20220314234659-1baeb1ce4c0b for Go… Also affects golang.org/x/crypto
- CVE-2020-9283 golang.org/x/crypto before v0.0.0-20200220183623-bac4c82f6975 for Go allows a panic… Also affects golang.org/x/crypto
- CVE-2026-33186 gRPC-Go is the Go language implementation of gRPC. Also affects aactl