Summary
The network address set API is missing from the auth object project-expansion switch, so a project-restricted client can read and rewrite the default project's address sets.
Details
Project confinement bypass on the network address set API
All six handlers in cmd/incusd/network_address_sets.go resolve the effective project via project.NetworkProject(), which returns "default" when the project does not have features.networks set. But expandProject in cmd/incusd/daemon.go (lines 326-372) has no branch for auth.ObjectTypeNetworkAddressSet, so the authorization object is constructed with the requested project instead of the effective one. Verified against the switch at HEAD c0ca96d, which handles Profile (352), StorageBucket (354), StorageVolume (356), NetworkZone (363), Image/ImageAlias (365) and Network/NetworkACL (367) — NetworkAddressSet appears nowhere.
Consequence: a certificate restricted to project P can read, rewrite, rename and delete the default project's address sets, which feed network ACL rules for every other tenant. features.networks defaults to false at project creation, so this is the default state of every project, not an unusual configuration.
Supporting evidence: the sibling auth.ObjectTypeNetworkACL is expanded on the same line, and the address-set LIST endpoint filters on the real project and correctly returns nothing — this is the only mismatch found when diffing every cmd/incusd caller of an effective-project resolver against the object types passed to allowPermission.
Suggested fixes
Add auth.ObjectTypeNetworkAddressSet to the expansion in expandProject alongside Network and NetworkACL. More durably, make expandProject fail closed on an unhandled object type rather than returning the requested project, so a future new API cannot repeat this.
Tooling and credit
AI assistance was used during investigation; the reporter read the full expandProject switch and confirmed the missing object type against its expanded siblings at HEAD, and independently confirmed the os.WriteFile call in instance_metadata.go.
Summary
The network address set API is missing from the auth object project-expansion switch, so a project-restricted client can read and rewrite the default project's address sets.
Details
Project confinement bypass on the network address set API
All six handlers in cmd/incusd/network_address_sets.go resolve the effective project via project.NetworkProject(), which returns "default" when the project does not have features.networks set. But expandProject in cmd/incusd/daemon.go (lines 326-372) has no branch for auth.ObjectTypeNetworkAddressSet, so the authorization object is constructed with the requested project instead of the effective one. Verified against the switch at HEAD c0ca96d, which handles Profile (352), StorageBucket (354), StorageVolume (356), NetworkZone (363), Image/ImageAlias (365) and Network/NetworkACL (367) — NetworkAddressSet appears nowhere.
Consequence: a certificate restricted to project P can read, rewrite, rename and delete the default project's address sets, which feed network ACL rules for every other tenant. features.networks defaults to false at project creation, so this is the default state of every project, not an unusual configuration.
Supporting evidence: the sibling auth.ObjectTypeNetworkACL is expanded on the same line, and the address-set LIST endpoint filters on the real project and correctly returns nothing — this is the only mismatch found when diffing every cmd/incusd caller of an effective-project resolver against the object types passed to allowPermission.
Suggested fixes
Add auth.ObjectTypeNetworkAddressSet to the expansion in expandProject alongside Network and NetworkACL. More durably, make expandProject fail closed on an unhandled object type rather than returning the requested project, so a future new API cannot repeat this.
Tooling and credit
AI assistance was used during investigation; the reporter read the full expandProject switch and confirmed the missing object type against its expanded siblings at HEAD, and independently confirmed the os.WriteFile call in instance_metadata.go.