Summary
When copying an instance across projects, the project restriction check (AllowInstanceCreation) runs BEFORE the source instance's configuration is merged into the request. Dangerous configuration keys (including security.privileged, raw.lxc, raw.apparmor) from the source instance are merged AFTER the check passes, bypassing all project restrictions on the target project.
Details
The vulnerability exists in cmd/incusd/instances_post.go:
- Line 1440:
project.AllowInstanceCreation(tx, targetProjectName, req) checks restrictions against req — at this point, req.Config is empty or contains only user-supplied overrides (typically none for a plain copy)
- Line 1528:
createFromCopy() is called AFTER the check passes
- Lines 680-691 (inside createFromCopy): Source instance config is iterated and ALL non-volatile keys are merged into
req.Config via InstanceIncludeWhenCopying()
internal/instance/config.go:1826: InstanceIncludeWhenCopying returns true for dangerous keys including security.privileged (config.go:956), raw.lxc (config.go:836), and raw.apparmor (config.go:293)
Notably, the backup restore path at lines 1013-1036 HAS a late restriction check after the instance is fully assembled — the copy path has no equivalent post-merge validation. This asymmetry strongly suggests an oversight.
Attack Chain
- Attacker has access to two projects: one unrestricted (or views instances in one), one restricted
- Source project has instance with
security.privileged=true and/or raw.lxc hooks
- Attacker sends:
POST /1.0/instances?project=restricted-project
{"name": "evil", "source": {"type": "copy", "source": "priv-container", "project": "unrestricted-project"}}
AllowInstanceCreation passes (req.Config is empty at check time)
createFromCopy merges source config including security.privileged=true
- Instance created in restricted project with unrestricted configuration
- Attacker starts instance → privileged container → host escape
Impact
Full container escape from a restricted project. An attacker who can view an instance in an unrestricted project and create instances in a restricted project can bypass all project-level security restrictions.
Preconditions
- Attacker has
CanView on a source instance in an unrestricted (or less-restricted) project
- Attacker has
CanCreateInstances in a restricted target project
- Source instance has dangerous configuration (security.privileged, raw.lxc, etc.)
Suggested Fix
Add a late restriction check in createFromCopy() AFTER the source config merge (after line 692), similar to the existing check in the backup restore path at lines 1013-1036. Validate the FINAL merged config against the target project's restrictions.
Credit
Vulnerability independently discovered and responsibly disclosed by Zhixi "Jace" Sun (@manus-use).
Summary
When copying an instance across projects, the project restriction check (
AllowInstanceCreation) runs BEFORE the source instance's configuration is merged into the request. Dangerous configuration keys (includingsecurity.privileged,raw.lxc,raw.apparmor) from the source instance are merged AFTER the check passes, bypassing all project restrictions on the target project.Details
The vulnerability exists in
cmd/incusd/instances_post.go:project.AllowInstanceCreation(tx, targetProjectName, req)checks restrictions againstreq— at this point,req.Configis empty or contains only user-supplied overrides (typically none for a plain copy)createFromCopy()is called AFTER the check passesreq.ConfigviaInstanceIncludeWhenCopying()internal/instance/config.go:1826:InstanceIncludeWhenCopyingreturnstruefor dangerous keys includingsecurity.privileged(config.go:956),raw.lxc(config.go:836), andraw.apparmor(config.go:293)Notably, the backup restore path at lines 1013-1036 HAS a late restriction check after the instance is fully assembled — the copy path has no equivalent post-merge validation. This asymmetry strongly suggests an oversight.
Attack Chain
security.privileged=trueand/orraw.lxchooksAllowInstanceCreationpasses (req.Config is empty at check time)createFromCopymerges source config includingsecurity.privileged=trueImpact
Full container escape from a restricted project. An attacker who can view an instance in an unrestricted project and create instances in a restricted project can bypass all project-level security restrictions.
Preconditions
CanViewon a source instance in an unrestricted (or less-restricted) projectCanCreateInstancesin a restricted target projectSuggested Fix
Add a late restriction check in
createFromCopy()AFTER the source config merge (after line 692), similar to the existing check in the backup restore path at lines 1013-1036. Validate the FINAL merged config against the target project's restrictions.Credit
Vulnerability independently discovered and responsibly disclosed by Zhixi "Jace" Sun (@manus-use).