mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-15 05:09:44 +08:00
* fix(policy): prevent implicit authorization inheritance A network rule authorizes every listed binary to reach every listed endpoint, so unioning an AddRule operation's binaries and endpoints independently grants binary-by-endpoint pairs the operation never declared. Require AddRule to declare the complete product before merging, and reject an operation that would give one host and port two different MCP inspection contracts. The rejection names the binaries the operation still has to declare. Fix proposal coverage on the same surface. An any-binary proposal was vacuously covered by a binary-restricted loaded rule, and a complete product split across several loaded rules was reported as uncovered. Coverage compares merge-widened endpoint fields by containment and exact-matches only the fields the merge never widens, so a policy the gateway just merged always reads back as covered and the sandbox policy.local /wait long-poll cannot spin to its deadline. Signed-off-by: Shiju <shiju@nvidia.com> * fix(policy): close authorization-inheritance gaps in merge and coverage Coverage treated an unset proposal value for a field the merge retains as a request for the default, so a proposal that merged cleanly into an endpoint carrying enforcement, protocol, or tls read back as uncovered and left the policy.local /wait long poll spinning. Unset now means unspecified. Ports are a set on the wire but each port is an independent authorization. Coverage and the inheritance check both resolve one binary, host, path, and port at a time, so ports spread across loaded rules resolve and a complete declaration split across incoming endpoints is accepted. An incoming empty binary list means any binary. It now has to declare every merged endpoint like a new concrete path does, and once declared the promotion is applied instead of appending an empty list and leaving the restricted scope in place. The endpoint-overlap fallback folded a new rule name into an existing rule where inheritance validation then rejected it, leaving no way to grant a binary part of a rule. Folding now keeps the requested rule name when it would widen, and reports that it did. An MCP contract conflict still propagates because one host and port carry a single inspection contract. AddAllowRules and AddDenyRules select an endpoint by host and port alone and now reject a target that resolves more than once, including two paths on one rule. RemoveBinary rejects an any-binary rule rather than reporting a success that leaves the binary authorized. Signed-off-by: Shiju <shiju@nvidia.com> * fix(policy): gate port and MCP-contract widening independently of binary scope The changed-port check only rejected when the operation also left an existing binary undeclared. An operation listing every existing binary could therefore declare one port of a multi-port endpoint and have its widened fields land on the endpoint the merge shares across all of them, authorizing L7 rules on a port it never named. Each changed port must now be named by the operation on its own, independently of binary-scope coverage. MCP contract compatibility was checked inside the endpoint fold, which only compares endpoints agreeing on host, path, and a shared port. The sandbox resolves one extended configuration per host and port and never consults the path, so a second MCP endpoint under another path, or in another rule, left the effective strict-tool-name, method-profile, and body-limit contract decided by match order. Contract agreement is now enforced across the whole merged policy, including provider-composed rules. A conflict already present in the baseline is left alone so unrelated updates still apply. An empty binary list authorizes any binary. Appending an incoming named list made it non-empty and revoked every process the operation did not name, turning an additive update into a silent mass revocation. An already-empty scope is now kept and reported; only a restricted scope is replaced by an incoming any-binary scope. Warnings raised during a fold now name the rule that was actually modified rather than the rule name the operation requested, which differ when the endpoint-overlap fallback redirects the operation. Signed-off-by: Shiju <shiju@nvidia.com> * fix(policy): route undeclared-port conflicts through the separate-rule fallback The fold-only classifier decides which merge errors disappear when the incoming authorization stays on its own rule. UndeclaredPortWouldChange was added ahead of the existing-binary conflict but never classified, so a differently named narrow update against a multi-port endpoint failed outright instead of landing separately. A same-key update still returns the error, because there the operation chose the target. The classifier is now an exhaustive match rather than a matches! with an implicit false. A new variant defaulting to "not fold-only" is what withdrew the separate-rule remedy here, so adding one has to be an explicit decision. Inspection-contract agreement now covers protocol, not only MCP options. The sandbox resolves one extended configuration per host and port and never consults the path, so an MCP endpoint and a REST endpoint on the same host and port left the effective inspection protocol decided by match order. Endpoints with no protocol carry no contract and are skipped. Signed-off-by: Shiju <shiju@nvidia.com> * fix(policy): compare only MCP contracts when detecting endpoint conflicts The post-merge conflict scan was broadened to compare inspection protocol as well as MCP options on one host and port. The supervisor selects among matching endpoint configs by most-specific path, so a broad REST endpoint and a narrower GraphQL endpoint on the same host and port are unambiguous and supported. The broader comparison rejected those updates even though the equivalent full policy loads and serves correctly. MCP options are not selected that way, so the scan keeps comparing them: two MCP endpoints on one host and port still have to agree on strict tool names, method profile, and body limit, whatever paths or rules hold them. The policy page returns to describing the MCP-specific rule and the path-aware selection it sits alongside. Signed-off-by: Shiju <shiju@nvidia.com> * fix(policy): keep MCP off a host and port shared with other inspection Narrowing the conflict scan back to MCP options let an MCP endpoint sit under a path already covered by a broader REST endpoint. The supervisor picks the parser by most-specific path, so the MCP endpoint parses the request, but _policy_allows_l7 is existential over every endpoint matching it. A plain REST rule on the overlapping path can therefore make allow_request true for a JSON-RPC tool call the MCP endpoint never allowed, and the relay forwards it. The scan now records every inspected protocol on a host and port. MCP may not share one with a differently inspected endpoint, and two MCP endpoints there still have to agree on one contract. Endpoints that are not inspected carry no contract and never compete, and two non-MCP endpoints stay supported because they share one method-and-path rule vocabulary. Signed-off-by: Shiju <shiju@nvidia.com> --------- Signed-off-by: Shiju <shiju@nvidia.com>