Access Control
This page describes go-pve-qemu's three guards: origin-scoped CORS, the ALLOW_IPS whitelist, and per-VM state and lock checks.
Layer 1: CORS
Every request passes the CORS middleware:
Origin |
Response |
|---|---|
A private IP (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) in the server's own /24 |
Access-Control-Allow-Origin echoes that origin |
| Any other origin | No Access-Control-Allow-Origin |
No Origin (curl, server-side callers) |
Unaffected |
The server subnet comes from the first non-loopback private IPv4 interface, falling back to 192.168.0.*. Allowed methods are GET, POST, OPTIONS; OPTIONS preflights get 204 directly.
CORS only constrains browsers; it is not authentication.
Layer 2: ALLOW_IPS
Every mutating endpoint (install, start, stop, shutdown, reboot, destroy, set/*) first matches the client IP:
ALLOW_IPS |
Behavior |
|---|---|
0.0.0.0 |
Allow all |
192.168.0.10,192.168.0.20 |
Allow only the listed IPs |
| unset or empty | Deny all |
The client IP comes from Gin's c.ClientIP(). The service sets no trusted proxies, so Gin honors X-Forwarded-For / X-Real-IP by default, and a client talking to the API directly can spoof its IP; expose the service only inside a controlled network.
Rejections look like this:
| Endpoint type | Response |
|---|---|
| Sync endpoints | 403 this IP is not allowed to perform this action |
| SSE endpoints | 200 with a single data: {"message": "...this IP is not allowed to perform this action"} line |
Query endpoints (health, list, status) do not check ALLOW_IPS.
Layer 3: VM State and the Disabled List
Mutating endpoints that target a VM check it against pvesh get /cluster/resources and .go_qemu_disabled:
| Check | Failure response |
|---|---|
| VM is on the disabled list | 400 this IP is not allowed to be controlled |
| Requires running, VM is stopped | 400 VM is not running |
| Requires stopped, VM is running | 400 VM is running |
| Cluster data or disabled list unreadable | 500 failed to get VM list: ... |
| Requires a running VM | Requires a stopped VM |
|---|---|
| stop, shutdown, reboot | start, destroy, set/cpu, set/memory, set/disk, set/node |
SSE endpoints report check failures as a single data: line as well.