Detect CVE-2026-46595: golang.org/x/crypto/ssh VerifiedPublicKeyCallback Authentication Bypass in Elastic Security
Detects exploitation of CVE-2026-46595, a critical authentication bypass vulnerability (CVSS 10.0) in golang.org/x/crypto/ssh versions prior to 0.52.0. When VerifiedPublicKeyCallback is used, SSH server implementations fail to enforce permission checks, allowing attackers to authenticate without proper authorization. This is a regression/variant of CVE-2024-45337 and carries a public PoC. Red Hat continues to issue errata across RHEL-derived ecosystems (RHSA-2026:23262, RHSA-2026:23264, RHSA-2026:26546, RHSA-2026:26547, RHSA-2026:30650, RHSA-2026:30651, RHSA-2026:33531, RHSA-2026:33524, RHSA-2026:36648, RHSA-2026:36207, RHSA-2026:36820, RHSA-2026:36808, RHSA-2026:36797, RHSA-2026:36796, RHSA-2026:36651, RHSA-2026:37387, RHSA-2026:37275, RHSA-2026:40118), indicating sustained, broad distribution-level patching activity as downstream vendors work through their release trains.
MITRE ATT&CK
Elastic Detection Query
sequence by host.name with maxspan=5m
[authentication where
event.action in ("ssh_login", "user_login", "authenticated") and
event.outcome == "success" and
(
process.name in ("sshd", "ssh") or
user_agent.original like~ "*golang*" or
user_agent.original like~ "*crypto/ssh*"
) and
authentication.type == "publickey"
] by source.ip, user.name
[network where
network.protocol == "ssh" and
event.action == "connection_attempted" and
source.ip != "127.0.0.1"
] by source.ip, user.name EQL sequence detection for CVE-2026-46595 that correlates successful SSH public key authentication with subsequent network connections, identifying potential authentication bypass exploitation on Go-based SSH servers.
Data Sources
Required Tables
False Positives & Tuning
- Authorized users performing SSH key-based logins followed by legitimate network activity
- Automated deployment and configuration management tools using SSH public key auth
- Security scanning tools performing authenticated SSH checks against managed hosts
- DevOps workflows involving SSH tunneling and port forwarding for development
Other platforms for CVE-2026-46595
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1CVE-2026-46595 PoC: VerifiedPublicKeyCallback Auth Bypass Simulation
Expected signal: SSH authentication log entry showing 'Accepted publickey for testuser' despite the key not being in the authorized_keys list or having required permissions. Process execution events showing 'id', 'hostname', and echo commands as child processes of the SSH daemon.
- Test 2Identify Vulnerable golang.org/x/crypto/ssh Deployments via Binary Inspection
Expected signal: Process execution events for 'go' binary with 'version -m' arguments, file access events on Go binaries in /usr/local/bin, /usr/bin, /opt, and /proc/*/exe paths.
- Test 3SSH Brute-Force Simulation Against Go SSH Server to Test Alerting
Expected signal: Multiple 'Invalid user' or 'Failed publickey' log entries from the lab host IP, followed by potential 'Accepted publickey' entries if testing against a vulnerable server. Network connection events on the SSH port from the test machine.
References (28)
- https://nvd.nist.gov/vuln/detail/CVE-2026-46595
- https://nvd.nist.gov/vuln/detail/CVE-2024-45337
- https://go.dev/cl/781642
- https://go.dev/issue/79570
- https://groups.google.com/g/golang-announce/c/a082jnz-LvI
- https://pkg.go.dev/vuln/GO-2026-5023
- https://github.com/advisories/GHSA-x527-x647-q7gg
- https://access.redhat.com/errata/RHSA-2026:23262
- https://access.redhat.com/errata/RHSA-2026:23264
- https://access.redhat.com/errata/RHSA-2026:26546
- https://access.redhat.com/errata/RHSA-2026:26547
- https://access.redhat.com/errata/RHSA-2026:30650
- https://access.redhat.com/errata/RHSA-2026:30651
- https://access.redhat.com/security/cve/CVE-2026-46595
- https://bugzilla.redhat.com/show_bug.cgi?id=2480689
- https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-46595.json
- https://access.redhat.com/errata/RHSA-2026:33531
- https://access.redhat.com/errata/RHSA-2026:33524
- https://access.redhat.com/errata/RHSA-2026:36648
- https://access.redhat.com/errata/RHSA-2026:36207
- https://access.redhat.com/errata/RHSA-2026:36820
- https://access.redhat.com/errata/RHSA-2026:36808
- https://access.redhat.com/errata/RHSA-2026:36797
- https://access.redhat.com/errata/RHSA-2026:36796
- https://access.redhat.com/errata/RHSA-2026:36651
- https://access.redhat.com/errata/RHSA-2026:37387
- https://access.redhat.com/errata/RHSA-2026:37275
- https://access.redhat.com/errata/RHSA-2026:40118
Response Playbook
Triage
- Identify all hosts running Go-based applications that implement SSH server functionality using golang.org/x/crypto/ssh versions prior to 0.52.0. Query your software inventory or SBOM for 'golang.org/x/crypto/ssh' dependencies. Red Hat errata (RHSA-2026:23262, RHSA-2026:23264, RHSA-2026:26546, RHSA-2026:26547, RHSA-2026:30650, RHSA-2026:30651, RHSA-2026:33531, RHSA-2026:33524, RHSA-2026:36648, RHSA-2026:36207, RHSA-2026:36820, RHSA-2026:36808, RHSA-2026:36797, RHSA-2026:36796, RHSA-2026:36651, RHSA-2026:37387, RHSA-2026:37275, RHSA-2026:40118) confirm broad and ongoing impact across RHEL-derived distributions — prioritize RHEL hosts running Go services and track the growing errata list as new package builds ship.
- Review SSH authentication logs on affected hosts for any publickey authentication successes, particularly from unexpected source IPs or for privileged accounts. Look for authentication events that bypass expected access control restrictions.
- Determine if VerifiedPublicKeyCallback is used in the application code by reviewing Go source or binary strings. Applications using this callback are specifically vulnerable to the permissions skip described in CVE-2026-46595.
- Cross-reference successful SSH authentication events with the authorized key list and expected access patterns. Any publickey auth success from unknown principals may indicate active exploitation.
- Check for lateral movement from compromised SSH servers — review outbound connections, process spawns, and file system modifications following suspicious authentication events.
Containment
- Immediately update golang.org/x/crypto/ssh to version 0.52.0 or later in all affected Go applications, rebuild, and redeploy. For RHEL-based systems, apply the relevant Red Hat errata (RHSA-2026:23262 through RHSA-2026:40118). If immediate patching is not possible, consider disabling the affected SSH server components or restricting network access via firewall rules.
- Rotate all SSH keypairs and revoke any keys that may have been used in exploitation. Audit authorized_keys files and application-level key trust stores for unauthorized entries added during a potential breach window.
- Isolate any hosts where suspicious successful publickey authentication was observed, particularly if followed by anomalous process execution or network connections, until forensic analysis is complete.
Evidence Collection
- Collect SSH authentication logs (/var/log/auth.log, /var/log/secure, journald SSH logs) from the time window of the suspected exploitation. Preserve these logs with timestamps and chain of custody documentation.
- Capture Go application binary versions and extract embedded module information using 'go version -m <binary>' or 'strings <binary> | grep golang.org/x/crypto' to confirm vulnerable version usage.
- Collect network flow records (NetFlow/IPFIX) for SSH connections (port 22 or custom SSH ports) to and from affected hosts during the investigation window to identify all sources that established SSH sessions.
Escalation Criteria
- !Escalate immediately if successful SSH authentication is confirmed from any external or unexpected IP address to a privileged account on a production system, as this indicates active exploitation with potential full system compromise.
- !Escalate if post-authentication activity is detected (command execution, file creation, network connections to C2 infrastructure) following anomalous SSH authentication events, indicating an active intrusion rather than a failed exploitation attempt.
Investigation Guide
Related Techniques
Forensic Artifacts
- >
SSH daemon authentication logs showing publickey auth successes: /var/log/auth.log (Debian/Ubuntu), /var/log/secure (RHEL/CentOS), journalctl -u ssh - >
Go application binary with embedded module metadata revealing golang.org/x/crypto/ssh version - >
Network capture (pcap) of SSH handshake showing publickey authentication exchange without proper server-side rejection - >
Process execution records from auditd or EDR showing commands spawned under the authenticated SSH session - >
File system timeline artifacts (new files, modified configurations) in the home directories of accounts targeted in the SSH authentication bypass
Tuning Guidance
Start with high-severity alerts for publickey authentication to privileged accounts (root, sudo-capable users) or from external IP ranges. Whitelist known CI/CD pipeline source IPs and authorized automation service accounts. For environments with high SSH volume, filter on the specific Go application SSH ports (non-standard ports often used by Go SSH servers) to reduce noise. Tune confidence from medium to high once you have confirmed the software inventory of vulnerable golang.org/x/crypto/ssh deployments in your environment. Consider correlating with SBOM or dependency data to scope detections only to hosts confirmed to run affected Go versions. Red Hat errata availability means RHEL-based hosts can be patched via standard yum/dnf update workflows — factor patched host lists into suppression rules to reduce noise post-remediation.
Hunting Queries
Hunt for SSH publickey authentication successes with zero corresponding failures on the same host — a strong indicator of the CVE-2026-46595 bypass where authentication succeeds without triggering normal rejection paths
Syslog
| where Facility == "auth"
| where SyslogMessage has "Accepted publickey"
| extend src_ip = extract("from ([\\d\.]+)", 1, SyslogMessage)
| extend username = extract("for ([\\w]+) from", 1, SyslogMessage)
| where isnotempty(src_ip) and isnotempty(username)
| summarize auth_count=count(), first_seen=min(TimeGenerated), last_seen=max(TimeGenerated) by src_ip, username, HostName
| where auth_count > 0
| join kind=leftouter (
Syslog
| where Facility == "auth"
| where SyslogMessage has "Failed"
| summarize fail_count=count() by HostName
) on HostName
| extend success_only = iif(isnull(fail_count) or fail_count == 0, true, false)
| where success_only == true
| sort by auth_count desc index=* sourcetype=linux_secure "Accepted publickey"
| rex field=_raw "from (?P<src_ip>[\d\.]+)"
| rex field=_raw "for (?P<username>\w+) from"
| stats count AS successes by src_ip, username, host
| appendcols
[search index=* sourcetype=linux_secure "Failed"
| stats count AS failures by host]
| where isnull(failures) OR failures=0
| sort - successes Hunt for suspicious process lineage following SSH authentication — identifies shells or scripting interpreters spawned as children of SSH processes, indicating possible post-exploitation command execution after CVE-2026-46595 bypass
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where FileName in~ ("sshd", "ssh") or ProcessCommandLine has "ssh"
| where InitiatingProcessFileName has_any ("bash", "sh", "python", "curl", "wget") or ParentProcessName has_any ("bash", "sh")
| where AccountName !in ("root", "sshd") or RemoteIP !startswith "10."
| project TimeGenerated, DeviceName, AccountName, ProcessCommandLine, InitiatingProcessFileName, RemoteIP, ParentProcessName
| sort by TimeGenerated desc index=* sourcetype=osquery name=process_events
| where parent_path LIKE "%ssh%" OR cmdline LIKE "%ssh%"
| where username NOT IN ("root", "sshd", "nobody")
| stats count by username, cmdline, parent_path, hostname
| where count > 0
| sort - count Atomic Red Team Tests
Simulates exploitation of CVE-2026-46595 by connecting to a Go SSH server using an unauthorized public key that should be rejected by permission enforcement but is accepted due to the VerifiedPublicKeyCallback bug. Requires a lab environment running a vulnerable Go SSH server (golang.org/x/crypto/ssh < 0.52.0).
Command
# Lab only — requires vulnerable Go SSH server at LAB_SSH_HOST:LAB_SSH_PORT
# Step 1: Generate a test keypair that is NOT in the authorized list
ssh-keygen -t ed25519 -f /tmp/test_bypass_key -N '' -C 'cve-2026-46595-test'
# Step 2: Attempt authentication with the unauthorized key
ssh -i /tmp/test_bypass_key -p ${LAB_SSH_PORT:-2222} -o StrictHostKeyChecking=no testuser@${LAB_SSH_HOST:-127.0.0.1} 'id; hostname; echo CVE-2026-46595 bypass successful' 2>&1
# Step 3: Record the authentication log entry
sudo journalctl -u ssh --since '1 minute ago' | grep -E 'Accepted|publickey|testuser' Cleanup
rm -f /tmp/test_bypass_key /tmp/test_bypass_key.pub Expected Telemetry
SSH authentication log entry showing 'Accepted publickey for testuser' despite the key not being in the authorized_keys list or having required permissions. Process execution events showing 'id', 'hostname', and echo commands as child processes of the SSH daemon.
Expected Detection
Triggers the KQL and SPL queries on 'Accepted publickey' events from an unexpected source. The hunting query for zero-failure auth hosts should fire if this is the only auth attempt from the test IP.
Scans running Go binaries and installed packages on a host to identify applications using vulnerable golang.org/x/crypto/ssh versions prior to 0.52.0, establishing the attack surface for CVE-2026-46595.
Command
# Scan running processes for Go binaries with embedded version info
for pid in $(ls /proc | grep '^[0-9]'); do
exe=$(readlink -f /proc/$pid/exe 2>/dev/null)
if [ -n "$exe" ] && file "$exe" 2>/dev/null | grep -q 'ELF'; then
version=$(go version -m "$exe" 2>/dev/null | grep 'golang.org/x/crypto' | awk '{print $3}')
if [ -n "$version" ]; then
echo "PID=$pid BINARY=$exe CRYPTO_VERSION=$version"
fi
fi
done
# Also scan common binary directories
find /usr/local/bin /usr/bin /opt -type f -executable 2>/dev/null | while read f; do
version=$(go version -m "$f" 2>/dev/null | grep 'golang.org/x/crypto' | awk '{print $3}')
if [ -n "$version" ]; then
echo "BINARY=$f CRYPTO_VERSION=$version"
fi
done Cleanup
No cleanup required — read-only reconnaissance operation Expected Telemetry
Process execution events for 'go' binary with 'version -m' arguments, file access events on Go binaries in /usr/local/bin, /usr/bin, /opt, and /proc/*/exe paths.
Expected Detection
Should NOT trigger detection rules (this is reconnaissance, not exploitation). However, results feed into asset inventory to scope which hosts require the CVE-2026-46595 KQL/SPL filters.
Simulates multiple SSH authentication attempts against a Go-based SSH server to validate that the detection queries fire correctly for authentication events. Tests both failed and suspicious-success scenarios.
Command
# Lab only — target a non-production SSH server
LAB_HOST=${LAB_SSH_HOST:-127.0.0.1}
LAB_PORT=${LAB_SSH_PORT:-2222}
# Generate multiple test keys
for i in 1 2 3; do
ssh-keygen -t ed25519 -f /tmp/test_key_$i -N '' -C "test_key_$i" 2>/dev/null
done
# Attempt authentication with each key (all should fail on patched server)
for i in 1 2 3; do
echo "--- Attempt $i ---"
ssh -i /tmp/test_key_$i -p $LAB_PORT \
-o StrictHostKeyChecking=no \
-o ConnectTimeout=5 \
-o BatchMode=yes \
testuser@$LAB_HOST 'id' 2>&1 || true
done
# Check auth log for the attempts
sudo journalctl -u ssh --since '2 minutes ago' | grep -E 'publickey|testuser|Invalid' Cleanup
rm -f /tmp/test_key_1 /tmp/test_key_1.pub /tmp/test_key_2 /tmp/test_key_2.pub /tmp/test_key_3 /tmp/test_key_3.pub Expected Telemetry
Multiple 'Invalid user' or 'Failed publickey' log entries from the lab host IP, followed by potential 'Accepted publickey' entries if testing against a vulnerable server. Network connection events on the SSH port from the test machine.
Expected Detection
Repeated failed authentication attempts should surface in SPL and KQL queries. On a vulnerable server, successful bypass authentication would generate 'Accepted publickey' telemetry triggering the primary detection rules.