GitHub
11/08/2026, 4:11 PMpkg/handlers.CreateQueryCarve combined them with utils.Intersect, which treated an empty side as "no filter": it returned the other side unchanged. So when one selector matched nothing, the result widened instead of becoming empty:
• platforms: [darwin], hosts: [web-1] against a Linux web-1 targeted web-1.
• environments: [missing], platforms: [linux] targeted every Linux node.
Since RBAC part 2, the caller's tier filter stops this from reaching nodes outside the caller's access. But within that access, queries and carves still ran on machines the operator did not select.
The whole-repo audit also found Carves.CheckCarve unused; GetCheckCarve replaced it.
What changes
• `CreateQueryCarve`: the first selector present sets the candidate nodes, and each later selector narrows them. A selector that matches nothing leaves no targets. A query with no selectors still targets every node in the environment, as before.
• utils.Intersect is now a plain intersection: an empty side gives an empty result. CreateQueryCarve was its only caller.
• Carves.CheckCarve is deleted. Nothing else in the code referenced it.
Security and operational impact
• Queries and carves no longer run on nodes the selectors excluded.
• Behavior change: a query or carve whose selectors can't all match now gets zero targets (Expected 0) instead of silently going to a wider set of nodes.
• No schema, API or UI changes.
Validation
• New `TestCreateQueryCarveEmptySelectorNarrowsToNothing`:
• a platform matching nothing plus a matching host gives nothing;
• an unknown environment plus a matching platform gives nothing;
• both matching gives the node.
The first two failed before the fix.
• TestIntersectEmpty now expects an empty result in both directions.
• The existing selector tests (environment thresholds, explicit UUID and host, no selectors) pass unchanged.
• go test ./... passes on an uncached run.
jmpsec/osctrlGitHub
11/08/2026, 4:36 PM