This is a safety catch that only fails after someone deliberately flips several other dangerous switches
CVE-2026-35385 affects OpenSSH before 10.3/10.3p1. When scp downloads a file as root, while forcing legacy SCP mode with -O, and without -p, the client may leave setuid or setgid bits on the downloaded file instead of clearing them. The result is not remote code execution in sshd; it is a dangerous permission outcome on the *client host* after a privileged file pull from an attacker-controlled or compromised source.
The vendor's 7.5/HIGH score overstates real enterprise risk. OpenSSH switched scp to SFTP by default years earlier, so the exposed population is already narrowed to workflows that explicitly opt back into legacy mode with -O; then you still need a root-run transfer, a malicious source endpoint, and a file that later gets executed. That is real risk for brittle admin automation, but it is nowhere near the operational urgency of an unauthenticated server-side SSH bug.
4 steps from start to impact.
Control the file source
sshd; the hostile logic lives on the *source side* of a client-initiated transfer.- Attacker controls the remote host or account that the victim will download from, or can tamper with that source path
- Victim uses
scpto pull content from that source
- Requires prior compromise or trusted access to a source endpoint
- Many enterprise transfers come from fixed internal systems, not arbitrary internet hosts
Trigger the legacy code path
scp as root and explicitly force legacy SCP/RCP with -O, while *not* using -p. That combination activates the old metadata-handling path where mode bits are not sanitized as expected. Since OpenSSH has used SFTP by default for scp since the 8.8 release train, this is an opt-in downgrade, not the mainstream path.- Victim runs the transfer as
root - Command line includes
-O - Command line omits
-p
- Modern
scpdefaults to SFTP, so-Omust be explicit - Running file pulls as
rootis common in some automation, but far from universal - A lot of enterprise scripts already use
sftp,rsync, package managers, or agent-based collection instead
scp -O or wrappers that force legacy SCP.Land a privileged file
setuid/setgid mode bits and content chosen by the attacker. Because the vulnerable client does not clear those bits in this exact mode, the destination file can be written with elevated permission metadata. That turns an ordinary root download into a potentially executable privilege-escalation artifact on disk.- Downloaded file carries mode bits meaningful on the destination filesystem
- Destination mount and OS honor
setuid/setgidsemantics
nosuidmounts kill a lot of the payoff- Setuid-on-scripts is ignored on many Unix-like systems; an ELF binary or other viable payload is needed
- If the file lands in a dead staging path and never executes, impact stops here
auditd, EDR, and periodic SUID/SGID sweeps can detect new privileged files after transfers. Version scanners can only tell you the binary is old, not whether the dangerous workflow exists.Convert it into privilege escalation or persistence
- A local execution path exists for the downloaded artifact
- The payload is actually runnable in a way that benefits from the preserved mode bits
- Needs post-download execution, not just file placement
- Least-privilege admin practices and staging controls often prevent execution from transfer directories
The supporting signals.
| In-the-wild status | No evidence of active exploitation in reviewed authoritative sources, and not listed in CISA KEV as of 2026-05-30. |
|---|---|
| PoC availability | No broadly circulated public exploit repo surfaced in reviewed sources. Reproduction is conceptually straightforward for anyone who controls the SCP source: serve a file with attacker-chosen content and privileged mode bits to a root-run legacy scp -O pull. |
| EPSS | User-supplied EPSS is 0.00058 (~0.058%), which is consistent with a very low near-term exploitation probability. |
| KEV status | No CISA KEV entry found; there is no federal due date pressure attached to this CVE. |
| CVSS vector reality check | CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H captures the theoretical impact after success, but it hides the biggest real-world friction: this is a client-side, root-run, legacy-mode workflow bug rather than a remotely reachable sshd flaw. |
| Affected versions | Upstream affects OpenSSH before 10.3/10.3p1. The vulnerable behavior is specifically in scp(1) when downloading as root with -O and without -p. |
| Fixed versions | Upstream fix lands in 10.3/10.3p1. Ubuntu backports already exist, including 24.04 LTS: 1:9.6p1-3ubuntu13.16 and 22.04 LTS: 1:8.9p1-3ubuntu0.15. |
| Exposure population | This is not meaningfully measurable by Shodan/Censys/GreyNoise the way an sshd bug would be, because exploitation depends on a client-side pull workflow. Exposure is materially reduced because OpenSSH switched scp to SFTP by default; you only hit the buggy path when automation explicitly forces legacy mode with -O. |
| Disclosure | Disclosed on 2026-04-02 in the OpenSSH 10.3 release cycle and reflected in NVD/MITRE records the same day. |
| Reporter | OpenSSH credits Christos Papakonstantinou of Cantina and Spearbit for reporting the bug. |
noisgate verdict.
The decisive factor is that exploitation requires a highly specific privileged workflow: a root-run scp download that explicitly forces legacy mode with -O from an attacker-controlled source. That sharply limits both reachable population and operational blast radius, so this behaves like a dangerous automation footgun, not a broadly exploitable SSH emergency.
Why this verdict
- -2.0 for attacker position: the attacker needs control of the remote file source or a prior compromise in that trust path; this is not unauthenticated reach to your exposed
sshdfleet. - -1.5 for explicit legacy opt-in: OpenSSH moved
scpto SFTP by default, so the vulnerable path only exists when operators or scripts deliberately force legacy SCP with-O. - -0.9 for privileged workflow rarity: the transfer must run as root and omit
-p; that is a narrow admin/automation pattern, not a default end-user behavior.
Why not higher?
It is not wormable, not internet-reachable in the usual SSH sense, and not useful without a malicious or compromised source endpoint plus a root-run download. There is also no KEV listing, no reviewed evidence of active exploitation, and very low EPSS pressure.
Why not lower?
If you do have brittle root-run automation using scp -O, this can silently plant SUID/SGID artifacts that become local privilege escalation or persistence later. The impact on an affected host is real; the problem is the population exposed, not the harmlessness of a successful exploit.
What to do — in priority order.
- Find
scp -Oin automation — Search shell scripts, CI jobs, cron, Ansible, Salt, Puppet, backup tooling, and network-device collection workflows for explicitscp -Ouse, especially underroot. For a LOW finding there is no SLA here beyond backlog hygiene, but this is the single best control because it identifies the tiny slice of your estate that is actually reachable. - Stop pulling files as root — Move transfers to an unprivileged service account, then copy into final locations with controlled ownership and mode-setting (
install,chmod,chown) after validation. For LOW, do this in the next normal engineering cycle; it removes the biggest amplifier in the chain. - Retire legacy SCP mode — Prefer default
scpbehavior over SFTP, plainsftp, orrsync -e ssh, and remove compatibility flags that force-Ounless there is a documented exception. Treat this as backlog hygiene for LOW severity, but use it to permanently collapse exposure. - Harden download destinations — Use
nosuidon staging/download filesystems where possible, and monitor for newly created SUID/SGID files after admin transfer jobs. For LOW, implement as part of routine platform hardening; this reduces impact even if a bad transfer still happens.
- Blocking inbound SSH alone doesn't solve it, because the vulnerable action is a client-initiated file pull and may target internal or already trusted sources.
- MFA on the SSH source is not enough; once the operator successfully authenticates, a compromised source can still hand back malicious file metadata and content.
- Internet-facing version scanning is weak here; it may tell you a host has old OpenSSH, but it cannot tell you whether that host ever runs
scp -Oas root.
Crowdsourced verification payload.
Run this on the target Linux/macOS host that has the OpenSSH client installed. Invoke it as sudo bash ./check-cve-2026-35385.sh so it can inspect common automation paths such as /etc, /opt, /usr/local, and cron; without root it may return UNKNOWN more often.
#!/usr/bin/env bash
# check-cve-2026-35385.sh
# Detect likely exposure to CVE-2026-35385 on hosts with OpenSSH client.
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN
# 3 = ERROR
set -u
have_cmd() { command -v "$1" >/dev/null 2>&1; }
version_lt() {
# returns 0 if $1 < $2
[ "$(printf '%s\n' "$1" "$2" | sort -V | head -n1)" != "$2" ]
}
extract_openssh_version() {
local out ver
if have_cmd ssh; then
out="$(ssh -V 2>&1)"
elif have_cmd scp; then
out="$(scp -V 2>&1 || true)"
else
return 1
fi
ver="$(printf '%s' "$out" | sed -n 's/.*OpenSSH[_ ]\([0-9][0-9.]*p\{0,1\}[0-9]*\).*/\1/p' | head -n1)"
[ -n "$ver" ] || return 1
# Normalize portable suffix, e.g. 10.2p1 -> 10.2.1 for sort -V
ver="$(printf '%s' "$ver" | sed 's/p/./')"
printf '%s\n' "$ver"
return 0
}
scan_for_legacy_root_scp() {
local hits=0 paths=()
local p
for p in /etc /usr/local /opt /root /var/spool/cron /etc/cron.d /etc/cron.daily /etc/cron.hourly /etc/cron.weekly /etc/cron.monthly; do
[ -e "$p" ] && paths+=("$p")
done
if [ ${#paths[@]} -eq 0 ]; then
return 2
fi
# Look for explicit -O use near scp invocation.
if grep -RIlE --exclude-dir='.git' --exclude='*.pyc' '(^|[^A-Za-z0-9_])scp([[:space:]].*)?[[:space:]]-O([[:space:]]|$)|(^|[^A-Za-z0-9_])scp[[:space:]].*-O([[:space:]]|$)' "${paths[@]}" >/tmp/cve2026_35385_hits.$$ 2>/dev/null; then
hits=$(wc -l < /tmp/cve2026_35385_hits.$$)
rm -f /tmp/cve2026_35385_hits.$$
[ "$hits" -gt 0 ] && return 0
fi
rm -f /tmp/cve2026_35385_hits.$$ 2>/dev/null || true
return 1
}
main() {
local ver fixed="10.3"
if ! have_cmd ssh && ! have_cmd scp; then
echo "UNKNOWN"
exit 2
fi
if ! ver="$(extract_openssh_version)"; then
echo "UNKNOWN"
exit 2
fi
if ! version_lt "$ver" "$fixed"; then
echo "PATCHED"
exit 0
fi
# Version is in affected range. Now look for real workflow exposure.
scan_for_legacy_root_scp
case $? in
0)
echo "VULNERABLE"
exit 1
;;
1)
echo "UNKNOWN"
exit 2
;;
*)
echo "UNKNOWN"
exit 2
;;
esac
}
main
If you remember one thing.
scp -O run as root; there is no noisgate mitigation SLA and no noisgate remediation SLA for a LOW finding, so treat it as backlog hygiene and fold upgrades to 10.3/10.3p1 or distro backports into your next normal client maintenance cycle.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.