Skip to content

feat(l7): add JSON-RPC policy enforcement#1865

Open
krishicks wants to merge 12 commits into
mainfrom
hicks/push-nvuozlywzuwu
Open

feat(l7): add JSON-RPC policy enforcement#1865
krishicks wants to merge 12 commits into
mainfrom
hicks/push-nvuozlywzuwu

Conversation

@krishicks

@krishicks krishicks commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds JSON-RPC L7 policy enforcement for sandbox proxy traffic. The implementation supports JSON-RPC endpoint configuration, rpc_method matching, scalar object params matching, forward-proxy inspection, CONNECT tunnel inspection, and deny-if-any-denied batch handling.

JSON-RPC enforcement applies to sandbox-to-server HTTP request bodies sent to the configured endpoint. It does not yet enforce policy on server-to-client JSON-RPC messages carried on MCP SSE streams or response bodies. Tool results continue to pass because responses are relayed, not matched against rpc_method.

Related Issue

Closes #1793

Changes

  • Add JSON-RPC as an L7 endpoint protocol in policy parsing, validation, proto conversion, and relay dispatch.
  • Parse JSON-RPC HTTP request bodies into normalized call metadata for single requests and batch arrays.
  • Extend OPA policy input and Rego rules to enforce rpc_method and flattened scalar object params matchers for allow and deny rules.
  • Inspect JSON-RPC request bodies on both forward-proxy and CONNECT tunnel paths before relaying upstream.
  • Evaluate JSON-RPC batch items independently and deny the whole batch when any call is denied.
  • Redact raw JSON-RPC params from L7 logs and record endpoint, RPC methods, params SHA-256 digest, and policy version instead.
  • Document current JSON-RPC directionality limits and params matcher scope.

Testing

  • mise run pre-commit passes
  • Unit tests added/updated
  • E2E tests added/updated (if applicable)

Additional targeted checks:

  • cargo test -p openshell-sandbox jsonrpc
  • mise run e2e:rust -- --test forward_proxy_jsonrpc_l7

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

@copy-pr-bot

copy-pr-bot Bot commented Jun 10, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@github-actions

Copy link
Copy Markdown

@krishicks krishicks force-pushed the hicks/push-nvuozlywzuwu branch 2 times, most recently from 62da29d to 8dc2a54 Compare June 11, 2026 15:20
@krishicks krishicks marked this pull request as ready for review June 12, 2026 16:35
@krishicks krishicks requested review from a team, derekwaynecarr and mrunalp as code owners June 12, 2026 16:35
@johntmyers johntmyers added the gator:in-review Gator is reviewing or awaiting PR review feedback label Jun 13, 2026
@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

PR Review Status

Validation: This maintainer-authored PR is project-valid because it implements the JSON-RPC/MCP method-level policy work discussed in #1793, with documented v1 scope around sandbox-to-server HTTP request inspection.
Head SHA: 8dc2a54f9b99d2aa297ccfd49c102ea10ce982f4

Review findings:

  • Blocking: crates/openshell-sandbox/src/l7/jsonrpc.rs flattens JSON-RPC params into dot-separated keys without rejecting literal dotted keys or collisions. A request can present arguments.scope as a top-level param while sending a different nested arguments.scope object path to the upstream server, which can bypass params selectors. Please fail closed on ambiguous/dotted param keys or preserve nested params through policy evaluation.
  • Blocking: crates/openshell-sandbox/src/proxy.rs only force-denies GraphQL parse errors in the forward-proxy path. JSON-RPC parse errors are carried in request_info.jsonrpc.error but can still be allowed by generic REST-style method/path rules such as access: full or read-write. Please include JSON-RPC parse errors in the same force-deny path.
  • Warning: forward-proxy JSON-RPC audit logs use generic FORWARD_L7 / l7 output and omit RPC methods, params digest, and policy version, while the CONNECT path has richer JSON-RPC logging.
  • Warning: json_rpc.on_parse_error and json_rpc.batch_policy appear accepted by policy YAML but are not enforced or converted into proto behavior. Please either implement them or reject/remove them from the accepted schema.

Docs: Fern docs were updated for the new policy schema and sandbox policy behavior.

Next state: gator:in-review

@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

PR Review Follow-Up

Head SHA: 8dc2a54f9b99d2aa297ccfd49c102ea10ce982f4

The required independent reviewer pass confirmed the two blocking findings from the previous gator review:

  • JSON-RPC params flattening can create a policy/upstream parser differential through dotted-key collisions.
  • Forward-proxy JSON-RPC parse errors are not force-denied, so invalid JSON-RPC can still be allowed by generic method/path rules.

Additional non-blocking warning from the independent review:

  • parse_jsonrpc_call accepts any object with a string method and does not require "jsonrpc": "2.0". If this endpoint is documented as JSON-RPC 2.0 enforcement, malformed objects should become parse errors and follow the same fail-closed path.

The earlier warnings also still apply: forward-proxy JSON-RPC audit logs are less detailed than CONNECT logs, and json_rpc.on_parse_error / json_rpc.batch_policy are accepted in YAML but not preserved or enforced in runtime policy semantics.

Next state: gator:in-review

@johntmyers johntmyers added the test:e2e Requires end-to-end coverage label Jun 15, 2026
@github-actions

Copy link
Copy Markdown

Label test:e2e applied for 8dc2a54. Open the existing run and click Re-run all jobs to execute with the label set. The run will execute the standard E2E suite after building the required gateway and supervisor images once. The matching required CI gate status on this PR will flip green automatically once the run finishes.

@ddurst-nvidia

ddurst-nvidia commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

I would recommend adding an Action to add a test the functionality from and to modelcontextprotocol/conformance and through OpenShell.

There is an action, but I don't think it's setup by default in a useful way for testing through OpenShell.

There everything-{client,server} stand ins that can be used to validate. If something isn't supported, we can just mark it as unsupported, but it reduces surprises for people using it.

@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

Re-check After Maintainer Update

I re-evaluated latest head 8dc2a54f9b99d2aa297ccfd49c102ea10ce982f4 after @ddurst-nvidia's 2026-06-15 comment recommending OpenShell-through-MCP conformance coverage.

Disposition: not resolved yet. There has not been a new commit or author response after the existing gator review feedback, and the maintainer testing recommendation is additional review feedback to address or have explicitly waived by a maintainer before this can advance.

Remaining items:

  • Blocking: JSON-RPC params matching still needs to fail closed on ambiguous dotted keys/collisions or preserve nested params through policy evaluation.
  • Blocking: JSON-RPC parse errors in the forward-proxy path still need the same fail-closed handling as GraphQL parse errors.
  • Review feedback: please address @ddurst-nvidia's recommendation for MCP conformance coverage through OpenShell, or get a maintainer decision that this does not need to block this PR.
  • Non-blocking warnings remain around forward-proxy JSON-RPC audit log detail, accepted-but-unenforced json_rpc.on_parse_error / json_rpc.batch_policy, and JSON-RPC 2.0 validation strictness.

Checks: required branch, Helm, DCO, docs preview, and standard Rust/Python checks are currently passing. OpenShell / E2E is still pending because the labeled E2E run needs execution.

Next state: gator:in-review

@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

Re-check After CI Update

I re-evaluated latest head 8dc2a54f9b99d2aa297ccfd49c102ea10ce982f4 after the labeled E2E run completed.

Disposition: not resolved. The PR still has unresolved review feedback, and the required OpenShell / E2E gate is now failing.

Remaining items:

  • Blocking: JSON-RPC params matching still needs to fail closed on ambiguous dotted keys/collisions or preserve nested params through policy evaluation.
  • Blocking: JSON-RPC parse errors in the forward-proxy path still need the same fail-closed handling as GraphQL parse errors.
  • Review feedback: please address @ddurst-nvidia's recommendation for MCP conformance coverage through OpenShell, or get a maintainer decision that this does not need to block this PR.
  • CI: OpenShell / E2E failed in run https://github.com/NVIDIA/OpenShell/actions/runs/27429202249. The failed jobs are e2e / E2E (rust-podman), e2e / E2E (rust-docker), e2e / E2E (rust-podman-rootless), e2e / E2E (python), and kubernetes-e2e / Kubernetes E2E (Rust smoke). The failed-log download was not available to this gator run, so a maintainer or author should inspect the failed Run tests steps in the Actions UI before deciding whether this is PR-caused or infrastructure-related.

Next state: gator:in-review

@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

Re-check After CI Log Review

I re-evaluated latest head 8dc2a54f9b99d2aa297ccfd49c102ea10ce982f4 after inspecting the failed OpenShell / E2E logs for run https://github.com/NVIDIA/OpenShell/actions/runs/27429202249.

Disposition: not resolved. The PR still has unresolved review feedback, and the failed E2E logs now show an actionable policy regression.

Remaining items:

  • Blocking: JSON-RPC params matching still needs to fail closed on ambiguous dotted keys/collisions or preserve nested params through policy evaluation.
  • Blocking: JSON-RPC parse errors in the forward-proxy path still need the same fail-closed handling as GraphQL parse errors.
  • Review feedback: please address @ddurst-nvidia's recommendation for MCP conformance coverage through OpenShell, or get a maintainer decision that this does not need to block this PR.
  • CI: OpenShell / E2E is failing. The logs show existing non-JSON-RPC L7 paths hitting an OPA evaluation error in crates/openshell-sandbox/data/sandbox-policy.rego: object.get(jsonrpc, "method", null) expects an object. This appears to make the new JSON-RPC matcher unsafe when request.jsonrpc is null/missing, causing GraphQL/HTTP L7 E2E regressions such as failed GraphQL forward/CONNECT tests, Python sandbox policy L7 tests returning status 0, and a Kubernetes smoke L7 bypass test returning 403 instead of 200.

Next state: gator:in-review

@krishicks krishicks force-pushed the hicks/push-nvuozlywzuwu branch 2 times, most recently from e9786e2 to 3516a0b Compare June 15, 2026 19:03
@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

Re-check After Author Update

I re-evaluated latest head 3516a0be911c2717d5789fde4ed6a70ea1a6a9c0 after the new commits addressing the prior JSON-RPC review feedback and adding MCP conformance coverage.

Disposition: partially resolved.

Resolved items:

  • JSON-RPC params matching now fails closed on literal dotted keys / flattened selector ambiguity.
  • Forward-proxy JSON-RPC parse errors now force-deny before generic L7 policy evaluation.
  • Unsupported json_rpc.on_parse_error / json_rpc.batch_policy YAML fields are now rejected instead of silently accepted.
  • MCP conformance coverage has been added, and the direct conformance runner command is wired in the expected client-mode shape.

Remaining items:

  • Blocking: crates/openshell-sandbox/data/sandbox-policy.rego still calls object.get on request.jsonrpc without first proving it is an object. The Rust L7 evaluator serializes non-JSON-RPC requests as "jsonrpc": null, so object.get(request, "jsonrpc", {}) can still return null and then object.get(jsonrpc, "method", null) can hit the same OPA type error seen in the prior E2E logs. Please guard with is_object(jsonrpc) and add a regression test for the actual "jsonrpc": null input shape.
  • Warning: .github/workflows/mcp-conformance.yml still checks out modelcontextprotocol/conformance by mutable tag v0.1.11 and runs npm ci / npm run build in a privileged Docker-socket job with job-level secrets. Please pin the upstream checkout to an immutable commit SHA for that release. Also consider narrowing/removing job-level credentials from the third-party build step.

Checks: current branch and E2E checks are queued or pending for this head, with test:e2e still applied.

Next state: gator:in-review

@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

Blocked

Gator is blocked because GitHub reports this PR is not mergeable against main (mergeable_state: dirty) at head 3516a0be911c2717d5789fde4ed6a70ea1a6a9c0.

Next action: @krishicks, please rebase or merge main and resolve the conflicts so review and CI monitoring can continue. The earlier JSON-RPC review feedback and the current CI status still need follow-up after the merge conflict is resolved.

@johntmyers johntmyers added gator:blocked Gator is blocked by process or repository gates and removed gator:in-review Gator is reviewing or awaiting PR review feedback labels Jun 15, 2026
@krishicks krishicks force-pushed the hicks/push-nvuozlywzuwu branch from 3516a0b to 6d61408 Compare June 15, 2026 19:25
Comment thread .github/workflows/mcp-conformance.yml Outdated
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
repository: modelcontextprotocol/conformance
ref: v0.1.11

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My last note on this got disappeared from history.

@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

Re-check After Author and Reviewer Updates

I re-evaluated latest head 6d614085a82404c0491de0af757e77f234d6631c after the new author commit and @ddurst-nvidia's 2026-06-15 review comment about MCP conformance coverage.

Disposition: still blocked. GitHub still reports this PR is not mergeable against main (mergeable_state: dirty), so review and CI monitoring cannot advance until the merge conflict is resolved.

Remaining items:

  • Blocker: @krishicks, please rebase or merge main and resolve the conflicts.
  • Review feedback: @ddurst-nvidia noted that the workflow still uses the older MCP conformance v0.1.11 release while v0.1.16 is available. Please address that or get a maintainer decision that the older release is intentional.
  • Earlier review feedback should be re-checked after the conflict is resolved and the final diff is stable.

Checks: required branch, Helm, DCO, Rust, Python, and license/header checks are passing for this head. OpenShell / E2E is currently pending with test:e2e applied, including the new MCP conformance job.

Next state: gator:blocked

@krishicks krishicks force-pushed the hicks/push-nvuozlywzuwu branch from 6d61408 to 9af3648 Compare June 15, 2026 20:31
@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

Re-check After Author Update

I re-evaluated latest head 9af36485ca1b8d81799338db56df340075b3b75b after @krishicks force-pushed new commits on 2026-06-15.

Disposition: still blocked. GitHub still reports this PR is not mergeable against main (mergeable_state: dirty), so review and CI monitoring cannot advance until the merge conflict is resolved.

Remaining items:

  • Blocker: @krishicks, please rebase or merge main and resolve the conflicts.
  • Review feedback to re-check after the conflict is resolved: the JSON-RPC Rego matcher still appears to call object.get on request.jsonrpc without proving it is an object, so the prior "jsonrpc": null regression concern may still apply.
  • Maintainer review feedback: the workflow now uses modelcontextprotocol/conformance v0.1.16, but the checkout is still by mutable tag rather than an immutable commit SHA.

Checks: branch, DCO, Rust, Python, license/header, and Helm checks are currently passing or skipped for this head. OpenShell / E2E is still in progress with test:e2e applied, but gator remains blocked on mergeability first.

Next state: gator:blocked

Add a Rust e2e test that drives MCP-style JSON-RPC requests through both the
forward proxy and CONNECT tunnel paths.

Cover method rules, params rules, batch handling, and invalid JSON denial
expectations so the JSON-RPC implementation can be built against one failing
scenario.

Signed-off-by: Kris Hicks <khicks@nvidia.com>
krishicks added 11 commits June 15, 2026 14:00
Add json-rpc as a policy protocol and carry JSON-RPC rule fields through policy
parsing and validation.

Wire the protocol into the L7 dispatcher with a passthrough placeholder so
later commits can add enforcement without changing endpoint recognition.

Signed-off-by: Kris Hicks <khicks@nvidia.com>
Move HTTP request body buffering and chunked-body normalization out of the
GraphQL module so other HTTP-carried L7 protocols can inspect request bodies
without depending on GraphQL internals.

Signed-off-by: Kris Hicks <khicks@nvidia.com>
Add the JSON-RPC HTTP parser and relay path, extract request methods, and pass
JSON-RPC metadata into L7 policy evaluation.

Wire rpc_method through proto and policy conversion, add Rego matching for
JSON-RPC methods, and inspect forward-proxy JSON-RPC bodies before relaying
upstream.

Signed-off-by: Kris Hicks <khicks@nvidia.com>
Carry JSON-RPC max body bytes from policy into runtime endpoint config and use
it on both CONNECT and forward JSON-RPC inspection paths instead of hardcoding
64 KiB.

Signed-off-by: Kris Hicks <khicks@nvidia.com>
Add JSON-RPC params matcher maps to proto and YAML policy conversion, including
shared matcher conversion helpers.

Flatten object params into dot-separated keys for policy input and extend Rego
allow and deny matching to filter JSON-RPC calls by params.

Signed-off-by: Kris Hicks <khicks@nvidia.com>
Parse JSON-RPC batch arrays into per-call metadata and evaluate each batch item
with the existing method and params policy rules.

Deny the whole batch when any call is denied.

Signed-off-by: Kris Hicks <khicks@nvidia.com>
Log JSON-RPC endpoint, RPC methods, params SHA-256 digest, and policy version
without recording raw params. Use <empty> when no params are present.

Signed-off-by: Kris Hicks <khicks@nvidia.com>
Document JSON-RPC endpoint configuration, rpc_method and params matchers, batch
denial behavior, current directionality limits, matcher scope, and the current
policy update CLI limitation.

Signed-off-by: Kris Hicks <khicks@nvidia.com>
Reject ambiguous JSON-RPC params before policy evaluation by refusing literal
dotted object keys and flattened selector collisions.

Force-deny JSON-RPC parse errors in the forward-proxy path so broad REST-style
access presets cannot bypass malformed JSON-RPC bodies.

Require JSON-RPC 2.0 request objects, use JSON-RPC-specific forward audit logs
with RPC methods, params digest, and policy generation, and reject unsupported
json_rpc YAML knobs instead of accepting unused fields.

Signed-off-by: Kris Hicks <khicks@nvidia.com>
Add a reusable MCP conformance workflow that runs upstream client scenarios
through an OpenShell sandbox.

Add a client image, wrapper, policy template, and expected-failures baseline
for expanding MCP conformance coverage.

Remove stale JSON-RPC e2e policy fields that are no longer accepted.

Signed-off-by: Kris Hicks <khicks@nvidia.com>
Signed-off-by: Kris Hicks <khicks@nvidia.com>
@krishicks krishicks force-pushed the hicks/push-nvuozlywzuwu branch from 9af3648 to 7101a37 Compare June 15, 2026 21:26
@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

Re-check After Author Update

I re-evaluated latest head 7101a37b3dd1fcfa36cb357cf3f5133b6c2fc295 after @krishicks pushed new commits on 2026-06-15.

Disposition: partially resolved. The prior merge-conflict blocker is no longer the active blocker: GitHub REST now reports mergeable: true and mergeable_state: blocked, which reflects remaining repository gates such as review/check status rather than the earlier dirty conflict state. Gator is returning this PR to gator:in-review.

Resolved items:

  • JSON-RPC params matching now rejects literal dotted keys and flattened selector collisions.
  • Forward-proxy JSON-RPC parse errors now force-deny before generic L7 policy evaluation.
  • Unsupported JSON-RPC policy fields are no longer silently accepted.
  • MCP conformance coverage has been added and updated to modelcontextprotocol/conformance v0.1.16.

Remaining items:

  • Blocking: crates/openshell-supervisor-network/data/sandbox-policy.rego still calls object.get on request.jsonrpc without first proving it is an object. Runtime-shaped non-JSON-RPC L7 inputs can contain "jsonrpc": null, so object.get(request, "jsonrpc", {}) can still return null and object.get(jsonrpc, "method", null) can hit the same OPA type error seen in the prior E2E logs. Please guard with is_object(jsonrpc) and add a regression test for the actual "jsonrpc": null input shape.
  • Warning: .github/workflows/mcp-conformance.yml still checks out upstream conformance by mutable tag v0.1.16 in a privileged Docker-socket job with token-bearing environment. Please pin the upstream checkout to the full commit SHA for that release, and consider moving registry/GitHub token environment to only the steps that need it.

Docs: present for the JSON-RPC policy schema and sandbox policy behavior.

Checks: OpenShell / Branch Checks, Helm, DCO, docs preview, Rust, Python, and build jobs are currently passing. OpenShell / E2E is still pending with test:e2e applied, but this PR cannot advance to gator:watch-pipeline until the blocking Rego feedback is resolved.

Next state: gator:in-review

@johntmyers johntmyers added gator:in-review Gator is reviewing or awaiting PR review feedback and removed gator:blocked Gator is blocked by process or repository gates labels Jun 15, 2026
@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

Re-check After CI Update

I re-evaluated latest head 7101a37b3dd1fcfa36cb357cf3f5133b6c2fc295 after the labeled E2E run completed: https://github.com/NVIDIA/OpenShell/actions/runs/27577493131

Disposition: not resolved. The PR still has unresolved review feedback, and the required OpenShell / E2E gate is now failing.

Remaining items:

  • Blocking: crates/openshell-supervisor-network/data/sandbox-policy.rego still needs to guard request.jsonrpc with is_object(jsonrpc) before calling object.get(jsonrpc, ...), plus a regression test for the runtime-shaped "jsonrpc": null input.
  • CI: OpenShell / E2E failed. The failed jobs are mcp-conformance / MCP Conformance, e2e / E2E (rust-docker), e2e / E2E (rust-podman), e2e / E2E (rust-podman-rootless), e2e / E2E (python), kubernetes-e2e / Kubernetes E2E (Rust smoke), and Core E2E result. The raw failed-log download is blocked from this sandbox by the external Actions log URL, and REST annotations only expose the failing steps/exit codes, so a maintainer or author should inspect the Actions logs before classifying any subset as infrastructure-related.
  • Warning: .github/workflows/mcp-conformance.yml still checks out upstream conformance by mutable tag v0.1.16 in a privileged Docker-socket job with token-bearing environment. Please pin the upstream checkout to the full commit SHA for that release, and consider moving registry/GitHub token environment to only the steps that need it.

Next state: gator:in-review

@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

PR Review Follow-Up

Head SHA: 7101a37b3dd1fcfa36cb357cf3f5133b6c2fc295

The required independent reviewer pass re-checked the current head. It confirms one blocking issue remains:

  • Blocking: crates/openshell-supervisor-network/data/sandbox-policy.rego still calls object.get on request.jsonrpc without first proving it is an object. Runtime-shaped non-JSON-RPC L7 inputs can contain "jsonrpc": null from crates/openshell-supervisor-network/src/l7/relay.rs, so JSON-RPC rule evaluation can still hit the OPA type error seen in the prior E2E failures. Please guard with is_object(jsonrpc) before object.get(jsonrpc, ...), guard params similarly, and add a regression test for a JSON-RPC endpoint/rule with request.jsonrpc: null.

Additional non-blocking warnings from this pass:

  • .github/workflows/mcp-conformance.yml still checks out modelcontextprotocol/conformance by mutable tag v0.1.16 inside a privileged Docker-socket job while job-level GitHub/registry credentials are present. Please pin the upstream checkout to the full commit SHA for that release, and narrow credential exposure where practical.
  • JSON-RPC params matcher validation does not appear to mirror the REST query matcher shape validation for allow or deny rules. Please reuse the query matcher validator for params on protocol: json-rpc so invalid matcher objects are rejected instead of accepted with unclear runtime behavior.

Checks: OpenShell / E2E is still failing for run https://github.com/NVIDIA/OpenShell/actions/runs/27577493131. Branch checks, Helm, DCO, docs preview, Rust, Python, and build jobs are passing for this head.

Next state: gator:in-review


##### JSON-RPC Deny Rule (`protocol: json-rpc`)

JSON-RPC deny rules use the same field names as JSON-RPC allow rules, but they appear directly under each `deny_rules` entry instead of under an `allow` wrapper. Deny rules take precedence over allow rules. In a batch request, one denied call denies the full batch.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sibling rules and deny_rules feels like an awkward pairing, especially since each rules is scoped by an allow. I'm guessing that the intent is to not complicate the deny > allow precedence as seen in a list, but I feel like that may be better managed as:

rules:
  deny:
    - rpc.method: tools/call
      params:
        name: delete_resource
    - rpc.method: something/else
  allow:
    - rpc.method: tools/call
      params:
        name: init
    - ...

Stating that "deny rules are applied first," is probably less complicated, than splitting at rules & deny_rules.

@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

Re-check After Reviewer Update

I re-evaluated latest head 7101a37b3dd1fcfa36cb357cf3f5133b6c2fc295 after @ddurst-nvidia's 2026-06-15 review comment on the JSON-RPC policy schema shape.

Disposition: not resolved. There has not been a new commit after the latest gator review pass, and the new schema feedback needs an author response or a maintainer decision before this can advance.

Remaining items:

  • Blocking: crates/openshell-supervisor-network/data/sandbox-policy.rego still needs to guard request.jsonrpc and params with object checks before calling object.get(...), plus a regression test for a JSON-RPC endpoint/rule with request.jsonrpc: null.
  • CI: OpenShell / E2E is failing in run https://github.com/NVIDIA/OpenShell/actions/runs/27577493131, including MCP conformance and the core E2E jobs.
  • Review feedback: please respond to @ddurst-nvidia's concern that the current sibling rules / deny_rules schema is awkward compared with a grouped allow/deny rule shape, or get a maintainer decision that the current schema should remain.
  • Warning: .github/workflows/mcp-conformance.yml still checks out upstream conformance by mutable tag v0.1.16 in a privileged Docker-socket job with token-bearing environment; please pin the upstream checkout to the full commit SHA for that release and narrow credential exposure where practical.
  • Warning: JSON-RPC params matcher validation should mirror REST query matcher validation for allow and deny rules so invalid matcher objects are rejected predictably.

Next state: gator:in-review

Comment thread proto/sandbox.proto
// GraphQL root field globs. Deny rules match when any selected root field
// matches any configured glob.
repeated string fields = 7;
// JSON-RPC method name (JSON-RPC): exact name or glob, e.g. "tools/call".

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

From the perspective of JSON-RPC 2.0, * is a valid method name, any string, not starting with rpc. is available for use.

From the perspective of MCP, there is (currently) an enumerated list of methods per version of the spec.

@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

Re-check After Reviewer Update

I re-evaluated latest head 7101a37b3dd1fcfa36cb357cf3f5133b6c2fc295 after @ddurst-nvidia's 2026-06-15 review comment on JSON-RPC rpc_method semantics in proto/sandbox.proto.

Disposition: not resolved. There has not been a new commit after the latest gator review pass, and existing review feedback plus failing E2E still block advancement.

Remaining items:

  • Blocking: crates/openshell-supervisor-network/data/sandbox-policy.rego still needs to guard request.jsonrpc and params with object checks before calling object.get(...), plus a regression test for a JSON-RPC endpoint/rule with request.jsonrpc: null.
  • CI: OpenShell / E2E is failing in run https://github.com/NVIDIA/OpenShell/actions/runs/27577493131, including MCP conformance and the core E2E jobs.
  • Review feedback: please respond to @ddurst-nvidia's concern that the current sibling rules / deny_rules schema is awkward compared with a grouped allow/deny rule shape, or get a maintainer decision that the current schema should remain.
  • Review feedback: please account for @ddurst-nvidia's note that JSON-RPC allows any non-rpc. string method name, while MCP has versioned method sets, so the rpc_method docs/comments should avoid implying * has special JSON-RPC meaning beyond OpenShell policy matching.
  • Warning: .github/workflows/mcp-conformance.yml still checks out upstream conformance by mutable tag v0.1.16 in a privileged Docker-socket job with token-bearing environment; please pin the upstream checkout to the full commit SHA for that release and narrow credential exposure where practical.
  • Warning: JSON-RPC params matcher validation should mirror REST query matcher validation for allow and deny rules so invalid matcher objects are rejected predictably.

Next state: gator:in-review

@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

PR Review Follow-Up

Head SHA: 7101a37b3dd1fcfa36cb357cf3f5133b6c2fc295

The required independent reviewer pass re-checked the current head. This PR remains blocked in gator:in-review.

Blocking items:

  • crates/openshell-supervisor-network/data/sandbox-policy.rego still needs to guard request.jsonrpc and JSON-RPC params with object/string checks before calling object.get(...), plus a regression test for a JSON-RPC endpoint/rule evaluated with runtime-shaped "jsonrpc": null. This likely explains the current OpenShell / E2E failures.
  • crates/openshell-supervisor-network/src/l7/relay.rs route-selected L7 handling only parses GraphQL request bodies. If multiple L7 endpoints share a host:port and the selected endpoint is protocol: json-rpc, request_info.jsonrpc remains empty, so JSON-RPC rules do not evaluate the body correctly. Please add JSON-RPC body inspection, parse-error force-deny, and batch evaluation semantics to the route-selected path as well.
  • OpenShell / E2E is still failing in run https://github.com/NVIDIA/OpenShell/actions/runs/27577493131, including MCP conformance and the core E2E jobs.
  • Review feedback still needs disposition: @ddurst-nvidia's schema-shape comment on sibling rules / deny_rules, and the rpc_method wording concern that * is OpenShell glob matching rather than JSON-RPC method syntax.

Non-blocking warnings:

  • JSON-RPC params matcher validation should reuse the REST query matcher validation shape for allow and deny rules.
  • The MCP conformance checkout should be pinned to an immutable commit SHA, and token-bearing environment should be scoped away from the third-party build step where practical.

Next state: gator:in-review

@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

PR Review Follow-Up

Head SHA: 7101a37b3dd1fcfa36cb357cf3f5133b6c2fc295

The required independent reviewer pass re-checked the current head. This PR remains in gator:in-review, but one prior blocker is now corrected: the current code does include JSON-RPC request body inspection, parse-error fail-closed handling, and batch evaluation semantics in the JSON-RPC L7 paths, so that route-selected L7 parsing concern is no longer blocking on code read.

Blocking items:

  • crates/openshell-supervisor-network/data/sandbox-policy.rego should still harden jsonrpc_rule_matches and params matching with is_object / is_string guards before calling object.get(...). Runtime-shaped inputs can carry "jsonrpc": null when metadata is absent, and this should cleanly non-match/default-deny rather than risk an OPA evaluation type error.
  • .github/workflows/mcp-conformance.yml still checks out modelcontextprotocol/conformance by mutable tag v0.1.16 and executes third-party Node code in a privileged Docker-socket job with token-bearing environment at job scope. Please pin the upstream checkout to a full commit SHA, set persist-credentials: false, and scope GitHub/GHCR token environment only to the steps that need it.
  • OpenShell / E2E is still failing in run https://github.com/NVIDIA/OpenShell/actions/runs/27577493131, including MCP conformance and the core E2E jobs.
  • Review feedback still needs disposition: @ddurst-nvidia's schema-shape comment on sibling rules / deny_rules, and the rpc_method wording concern that * is OpenShell glob matching rather than JSON-RPC method syntax.

Non-blocking warning:

  • JSON-RPC params matcher validation should reuse the REST query matcher validation shape for allow and deny rules so invalid matcher objects are rejected predictably.

Next state: gator:in-review

@johntmyers

Copy link
Copy Markdown
Collaborator

gator-agent

PR Review Follow-Up

Head SHA: 7101a37b3dd1fcfa36cb357cf3f5133b6c2fc295

The required independent reviewer pass re-checked the current head. This PR remains in gator:in-review.

Blocking items:

  • crates/openshell-supervisor-network/src/l7/relay.rs route-selected L7 handling still only inspects GraphQL request bodies. When multiple L7 endpoints share a host:port and the selected path is protocol: json-rpc, the route-selected path builds L7RequestInfo with jsonrpc: None, so JSON-RPC rules are not evaluated against the request body. Please add JSON-RPC body inspection, parse-error force-deny, batch evaluation/log semantics, and a regression test for the route-selected JSON-RPC path.
  • crates/openshell-supervisor-network/data/sandbox-policy.rego should harden jsonrpc_rule_matches and params matching with is_object / is_string guards before calling object.get(...). Runtime-shaped inputs can carry "jsonrpc": null when metadata is absent, and this should cleanly non-match/default-deny rather than risk an OPA evaluation type error.
  • JSON-RPC rpc_method and params policy fields need validation for both allow and deny rules. Please require a non-empty rpc_method for JSON-RPC rules, reject rpc_method / params on other protocols, and reuse the REST query matcher validator for params so invalid matcher objects do not silently fail open.
  • .github/workflows/mcp-conformance.yml still checks out upstream conformance by mutable tag v0.1.16 and executes third-party Node code in a privileged Docker-socket job with token-bearing environment at job scope. Please pin the upstream checkout to a full commit SHA, set persist-credentials: false, and scope registry/GitHub token environment only to the steps that need it.
  • OpenShell / E2E is still failing in run https://github.com/NVIDIA/OpenShell/actions/runs/27577493131, including MCP conformance and the core E2E jobs.
  • Review feedback still needs disposition: @ddurst-nvidia's schema-shape comment on sibling rules / deny_rules, and the rpc_method wording concern that * is OpenShell glob matching rather than JSON-RPC method syntax.

Non-blocking warnings:

  • The raw YAML OPA loader appears to recognize only internal json_rpc_max_body_bytes, while public docs and policy serialization use nested json_rpc.max_body_bytes. If that loader remains production-facing, please normalize the documented nested shape before L7 config parsing.
  • JSON-RPC method names are untrusted request body fields and are written directly into audit log text; consider escaping or control-character sanitization before joining method names.

Next state: gator:in-review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gator:in-review Gator is reviewing or awaiting PR review feedback test:e2e Requires end-to-end coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support method-level governance for MCP tool calls (JSON-RPC) in sandbox policy

3 participants