← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-35385 · CWE-281 · Disclosed 2026-04-02

In OpenSSH before 10

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

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.

"A root-run legacy SCP footgun, not an internet-reachable OpenSSH fire drill"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Control the file source

The attacker needs control of the remote SSH/SCP endpoint, the account serving the file, or a position to tamper with what the client is downloading. In practice this means compromising the source host, abusing a trusted jump box, or convincing an admin to pull from an attacker-operated system. This is not an attack against your exposed sshd; the hostile logic lives on the *source side* of a client-initiated transfer.
Conditions required:
  • Attacker controls the remote host or account that the victim will download from, or can tamper with that source path
  • Victim uses scp to pull content from that source
Where this breaks in practice:
  • Requires prior compromise or trusted access to a source endpoint
  • Many enterprise transfers come from fixed internal systems, not arbitrary internet hosts
Detection/coverage: External vuln scanners will miss this prerequisite entirely. Hunt for risky trust paths instead: root-run pull jobs, backup scripts, and network-device collection workflows.
STEP 02

Trigger the legacy code path

The victim must run 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.
Conditions required:
  • Victim runs the transfer as root
  • Command line includes -O
  • Command line omits -p
Where this breaks in practice:
  • Modern scp defaults to SFTP, so -O must be explicit
  • Running file pulls as root is common in some automation, but far from universal
  • A lot of enterprise scripts already use sftp, rsync, package managers, or agent-based collection instead
Detection/coverage: Good coverage by config/code search, weak coverage by network scanning. Grep repos, cron, Ansible, Salt, Puppet, and shell history for scp -O or wrappers that force legacy SCP.
STEP 03

Land a privileged file

A malicious SCP source can present a file with 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.
Conditions required:
  • Downloaded file carries mode bits meaningful on the destination filesystem
  • Destination mount and OS honor setuid/setgid semantics
Where this breaks in practice:
  • nosuid mounts 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
Detection/coverage: FIM, 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.
STEP 04

Convert it into privilege escalation or persistence

The attacker still needs the dropped file to be executed by a local user, an operator, or another process on the target host. If that happens and the payload is a valid setuid-root binary, this can become local privilege escalation or durable persistence. The blast radius is the specific host or small set of hosts running the bad automation, not the whole SSH estate.
Conditions required:
  • A local execution path exists for the downloaded artifact
  • The payload is actually runnable in a way that benefits from the preserved mode bits
Where this breaks in practice:
  • Needs post-download execution, not just file placement
  • Least-privilege admin practices and staging controls often prevent execution from transfer directories
Detection/coverage: EDR should be able to alert on execution of newly created SUID binaries or unusual exec-from-staging behavior. Baseline scans for new SUID/SGID files are high-value here.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo evidence of active exploitation in reviewed authoritative sources, and not listed in CISA KEV as of 2026-05-30.
PoC availabilityNo 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.
EPSSUser-supplied EPSS is 0.00058 (~0.058%), which is consistent with a very low near-term exploitation probability.
KEV statusNo CISA KEV entry found; there is no federal due date pressure attached to this CVE.
CVSS vector reality checkCVSS: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 versionsUpstream 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 versionsUpstream 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 populationThis 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.
DisclosureDisclosed on 2026-04-02 in the OpenSSH 10.3 release cycle and reflected in NVD/MITRE records the same day.
ReporterOpenSSH credits Christos Papakonstantinou of Cantina and Spearbit for reporting the bug.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.1/10)

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.

HIGH Downgrade from vendor HIGH due to compounding workflow prerequisites
MEDIUM Estate-specific exposure depending on how often `scp -O` is used in privileged automation

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 sshd fleet.
  • -1.5 for explicit legacy opt-in: OpenSSH moved scp to 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.

05 · Compensating Control

What to do — in priority order.

  1. Find scp -O in automation — Search shell scripts, CI jobs, cron, Ansible, Salt, Puppet, backup tooling, and network-device collection workflows for explicit scp -O use, especially under root. 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.
  2. 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.
  3. Retire legacy SCP mode — Prefer default scp behavior over SFTP, plain sftp, or rsync -e ssh, and remove compatibility flags that force -O unless there is a documented exception. Treat this as backlog hygiene for LOW severity, but use it to permanently collapse exposure.
  4. Harden download destinations — Use nosuid on 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.
What doesn't work
  • 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 -O as root.
06 · Verification

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.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/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
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, do not burn a fleetwide emergency window on this one. Spend this week inventorying OpenSSH clients below 10.3 and, more importantly, grepping automation for 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

  1. OpenSSH release notes
  2. OpenSSH 10.3 release announcement on oss-security
  3. NVD entry for CVE-2026-35385
  4. Ubuntu security tracker for CVE-2026-35385
  5. Debian security tracker for CVE-2026-35385
  6. CISA Known Exploited Vulnerabilities Catalog
  7. FIRST EPSS API documentation
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.