# [CRIT] [GHSA / CRITICAL] CVE-2026-45695: Kopia: RCE via SSH ProxyCommand Injection

**Source:** GitHub Security Advisories
**Published:** 2026-05-19
**Article:** https://github.com/advisories/GHSA-2q4c-3mrw-63c3

## Threat Profile

Kopia: RCE via SSH ProxyCommand Injection

## Summary

Kopia's HTTP server, when started with `--without-password `, accepts unauthenticated requests to `/api/v1/repo/exists`. The handler forwards an attacker-supplied storage configuration to `blob.NewStorage`. For SFTP backends with `externalSSH: true`, that path constructs a process command line by splitting `sshArguments` on spaces and passes the result directly to `exec.CommandContext("ssh")`. An `-oProxyCommand=<cmd>` token in `sshArguments…

## Indicators of Compromise (high-fidelity only)

- **CVE:** `CVE-2026-45695`

## MITRE ATT&CK Techniques

- **T1190** — Exploit Public-Facing Application
- **T1059.004** — Command and Scripting Interpreter: Unix Shell
- **T1059.003** — Command and Scripting Interpreter: Windows Command Shell
- **T1059.001** — Command and Scripting Interpreter: PowerShell
- **T1203** — Exploitation for Client Execution

## Kill chain phases observed

_(none detected from narrative keywords)_

## Recommended hunts

### Kopia process spawns ssh with -oProxyCommand= argument (CVE-2026-45695)

`UC_252_1` · phase: **exploit** · confidence: **High** · AI-generated for this article

**Splunk SPL (CIM):**
```spl
| tstats summariesonly=t count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where Processes.parent_process_name IN ("kopia","kopia.exe","kopia-ui","kopia-ui.exe") AND Processes.process_name IN ("ssh","ssh.exe") AND (Processes.process="*ProxyCommand*" OR Processes.process="*-oProxyCommand*" OR Processes.process="*-o ProxyCommand*") by host Processes.user Processes.parent_process_name Processes.parent_process Processes.process_name Processes.process Processes.process_path | `drop_dm_object_name(Processes)` | convert ctime(firstTime) ctime(lastTime)
```

**Defender KQL:**
```kql
DeviceProcessEvents
| where Timestamp > ago(7d)
| where InitiatingProcessFileName in~ ("kopia","kopia.exe","kopia-ui","kopia-ui.exe")
| where FileName in~ ("ssh","ssh.exe")
| where ProcessCommandLine has "ProxyCommand"
| where AccountName !endswith "$"
| project Timestamp, DeviceName, AccountName, InitiatingProcessFolderPath, InitiatingProcessCommandLine, FolderPath, ProcessCommandLine, ProcessId, InitiatingProcessId, SHA256
| order by Timestamp desc
```

### SSH process spawned by Kopia invokes a shell child (ProxyCommand execution)

`UC_252_2` · phase: **install** · confidence: **High** · AI-generated for this article

**Splunk SPL (CIM):**
```spl
| tstats summariesonly=t count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where Processes.parent_process_name IN ("ssh","ssh.exe") AND Processes.process_name IN ("sh","bash","dash","zsh","ksh","cmd.exe","powershell.exe","pwsh.exe","pwsh") by host Processes.user Processes.parent_process Processes.process_name Processes.process Processes.process_path | `drop_dm_object_name(Processes)` | join type=inner host parent_process [| tstats summariesonly=t count from datamodel=Endpoint.Processes where Processes.process_name IN ("ssh","ssh.exe") AND Processes.parent_process_name IN ("kopia","kopia.exe","kopia-ui","kopia-ui.exe") by host Processes.process as parent_process | `drop_dm_object_name(Processes)`] | convert ctime(firstTime) ctime(lastTime)
```

**Defender KQL:**
```kql
let kopia_ssh =
    DeviceProcessEvents
    | where Timestamp > ago(7d)
    | where InitiatingProcessFileName in~ ("kopia","kopia.exe","kopia-ui","kopia-ui.exe")
    | where FileName in~ ("ssh","ssh.exe")
    | project SshTime = Timestamp, DeviceId, SshPid = ProcessId, SshCmd = ProcessCommandLine, KopiaCmd = InitiatingProcessCommandLine;
DeviceProcessEvents
| where Timestamp > ago(7d)
| where InitiatingProcessFileName in~ ("ssh","ssh.exe")
| where FileName in~ ("sh","bash","dash","zsh","ksh","cmd.exe","powershell.exe","pwsh.exe","pwsh")
| join kind=inner kopia_ssh on $left.DeviceId == $right.DeviceId and $left.InitiatingProcessId == $right.SshPid
| where Timestamp between (SshTime .. SshTime + 30s)
| project Timestamp, DeviceName, AccountName, KopiaCmd, SshCmd, ShellImage = FolderPath, ShellCmd = ProcessCommandLine, SshPid
| order by Timestamp desc
```

### IOC-driven hunts (use shared templates)

These are standard IOC-substitution hunts — the canonical SPL and KQL live once in [`_TEMPLATES.md`](../_TEMPLATES.md), so we don't repeat the same boilerplate on every CVE / hash / network-IOC briefing.

- **Asset exposure — vulnerability matches article CVE(s)** ([template](../_TEMPLATES.md#asset-exposure)) — phase: **recon**, confidence: **High**
  - CVE(s): `CVE-2026-45695`


## Why this matters

Severity classified as **CRIT** based on: CVE present, 3 use case(s) fired, 5 technique(s) inferred. Read the full article for actor attribution, tooling details, and any defanged IOCs in the body that aren't visible in the RSS summary.
