# Incus container environment configuration newline injection

Incus didn't sanitize newlines in container environment variable values, letting an incus-group user inject lxc.hook.pre-start into lxc.conf and run commands as root on the host.

- Payout: Research
- Severity: high
- Program: Incus
- Found by: rmcnamara-snyk
- Disclosed: 2026-01-22
- CVE: CVE-2026-23953
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-x6jc-phwx-hp32
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-x6jc-phwx-hp32
- Tags: area:cloud domain:infra impact:privesc impact:rce kind:research platform:ghsa sev:high tech:go technique:source-review vuln:command-injection vuln:crlf-injection vuln:privilege-escalation

**Target:** Incus container config generation (lxc.conf writer)
**Root cause:** Environment variable values from the container config block are written into the generated lxc.conf without checking for newlines, so a multiline value injects arbitrary additional config keys.
**Steps:**
1. Launch a container with a YAML config where an environment variable value is a multiline string: `incus launch images:alpine/edge --ephemeral poc << EOF` with `config:` / `environment.FOO: |-` / `abc` / `lxc.hook.pre-start = /bin/sh -c "id > /newline_injection_command_exec_poc"`
2. Inspect the generated `/run/incus/user-1000_poc/lxc.conf` and observe the injected `lxc.hook.pre-start` item
3. Observe `/newline_injection_command_exec_poc` created on the host root filesystem, proving root command execution
4. On IncusOS, adjust the payload to write to a different writable directory (e.g. /tmp) for the validation step
**How found:** Code review of the config-to-lxc.conf generation path (driver_lxc.go) noting environment variable values were not checked for newlines before being written into the config file.
**Exploitation:** An attacker who can launch a container with a custom YAML config (e.g. member of the incus group) supplies a multiline environment variable value; the injected `lxc.hook.pre-start` line is written into lxc.conf and executed by LXC at container start, running the attacker's command as root on the host.
**Escalation:** Low-privileged incus-group container-launch permission escalates to root on the host via the pre-start lifecycle hook.
**Insight:** When a privileged daemon serializes user-controlled values into a line-oriented config file (lxc.conf, systemd units, ini files), test multiline values: a newline in an env var value can inject sibling config keys like lifecycle hooks that execute as root.

## Proof of concept (copied exactly from the original report)

**incus launch with newline-injected env var hook**

```
incus launch images:alpine/edge --ephemeral poc << EOF
config:
  environment.FOO: |-
    abc
    lxc.hook.pre-start = /bin/sh -c "id > /newline_injection_command_exec_poc"
EOF
```

