You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/reference/policy-schema.mdx
+72-6Lines changed: 72 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -155,7 +155,7 @@ Each endpoint defines a reachable destination and optional inspection rules.
155
155
| `host` | string | Yes | Hostname or IP address. Supports a `*` wildcard inside the first DNS label only: `*.example.com`, `**.example.com`, and intra-label patterns like `*-aiplatform.googleapis.com` are accepted; bare `*`/`**`, TLD wildcards (`*.com`), and wildcards outside the first label are rejected at load time. |
156
156
| `port` | integer | Yes | TCP port number. |
157
157
| `path` | string | No | Optional HTTP path glob used to select between L7 endpoints that share the same host and port. Empty means all paths. Use this when REST and GraphQL live under the same host, such as `/repos/**` and `/graphql`. |
158
-
| `protocol` | string | No | Set to `rest` for HTTP method/path inspection, `websocket` for RFC 6455 upgrade and client text-message inspection, or `graphql` for GraphQL-over-HTTP operation inspection. WebSocket endpoints can also use GraphQL operation rules for GraphQL-over-WebSocket traffic. Omit for TCP passthrough. |
158
+
| `protocol` | string | No | Set to `rest` for HTTP method/path inspection, `websocket` for RFC 6455 upgrade and client text-message inspection, `graphql` for GraphQL-over-HTTP operation inspection, or `json-rpc` for sandbox-to-server JSON-RPC-over-HTTP method and params inspection. WebSocket endpoints can also use GraphQL operation rules for GraphQL-over-WebSocket traffic. Omit for TCP passthrough. |
159
159
| `tls` | string | No | TLS handling mode. The proxy auto-detects TLS by peeking the first bytes of each connection and terminates it for inspected HTTPS traffic, so this field is optional in most cases. Set to `skip` to disable auto-detection for edge cases such as client-certificate mTLS or non-standard protocols. The values `terminate` and `passthrough` are deprecated and log a warning; they are still accepted for backward compatibility but have no effect on behavior. |
160
160
| `enforcement` | string | No | `enforce` actively blocks disallowed requests. `audit` logs violations but allows traffic through. |
161
161
| `access` | string | No | Access preset. One of `read-only`, `read-write`, or `full`. Mutually exclusive with `rules`. |
@@ -168,18 +168,21 @@ Each endpoint defines a reachable destination and optional inspection rules.
168
168
| `persisted_queries` | string | No | GraphQL hash-only behavior for `protocol: graphql` and GraphQL-over-WebSocket operation policy. Default is `deny`; use `allow_registered` only with `graphql_persisted_queries`. |
169
169
| `graphql_persisted_queries` | map | No | Trusted GraphQL persisted-query registry keyed by hash or saved-query ID. Values contain `operation_type`, optional `operation_name`, and optional root `fields`. |
170
170
| `graphql_max_body_bytes` | integer | No | Maximum GraphQL-over-HTTP request body bytes buffered for inspection. Defaults to `65536`. |
171
+
| `json_rpc` | object | No | JSON-RPC endpoint options. For `protocol: json-rpc`, `json_rpc.max_body_bytes` sets the maximum JSON-RPC-over-HTTP request body bytes buffered for inspection. Defaults to `65536`. |
171
172
172
173
Credential rewrite recognizes the canonical `openshell:resolve:env:KEY` placeholder form and whole-token provider-shaped aliases such as `provider-OPENSHELL-RESOLVE-ENV-API_TOKEN` when the referenced environment key exists in the configured provider credentials.
173
174
174
175
#### Access Levels
175
176
176
177
The `access` field accepts one of the following values:
| `full` | All methods and paths. | WebSocket upgrade and all inspected client text-message paths. | All operation types. | Allows matching HTTP requests without constraining JSON-RPC methods. |
182
+
| `read-only` | `GET`, `HEAD`, `OPTIONS`. | WebSocket upgrade handshake only. | `query` operations. | Expands to HTTP read methods and does not allow typical JSON-RPC `POST` calls. |
183
+
| `read-write` | `GET`, `HEAD`, `OPTIONS`, `POST`, `PUT`, `PATCH`. | WebSocket upgrade handshake and client text messages. | `query` and `mutation` operations. | Allows matching HTTP write requests without constraining JSON-RPC methods. |
184
+
185
+
For JSON-RPC endpoints, prefer explicit `rules` with `rpc_method` and optional `params` when you need method-level control.
183
186
184
187
#### Allow Rule Objects
185
188
@@ -274,6 +277,42 @@ rules:
274
277
275
278
Do not combine `method`, `path`, or `query` with `operation_type`, `operation_name`, or `fields` inside the same WebSocket rule. When a WebSocket endpoint has GraphQL operation policy, use GraphQL rules for client messages instead of a raw `WEBSOCKET_TEXT` allow rule.
276
279
280
+
##### JSON-RPC Allow Rule (`protocol: json-rpc`)
281
+
282
+
JSON-RPC allow rules match sandbox-to-server JSON-RPC-over-HTTP request objects by RPC method and optional params. They apply to single JSON-RPC requests and batch requests. For a batch, OpenShell evaluates each call independently. JSON-RPC responses and server-to-client messages on response bodies or MCP SSE streams are relayed but are not currently parsed for policy enforcement.
283
+
284
+
| Field | Type | Required | Description |
285
+
|---|---|---|---|
286
+
| `rpc_method` | string | Yes | JSON-RPC method name or glob, such as `initialize`, `tools/list`, or `tools/*`. |
287
+
| `params` | map | No | Params matchers keyed by flattened object-param path. Use dot-separated keys for nested object params, such as `arguments.scope`. Matcher value can be a glob string or an object with `any`. Strings, numbers, and booleans are converted to strings; arrays, `null`, and non-object top-level params do not produce matcher keys. |
288
+
289
+
Example JSON-RPC allow rules:
290
+
291
+
```yaml showLineNumbers={false}
292
+
endpoints:
293
+
- host: mcp.example.com
294
+
port: 443
295
+
path: /mcp
296
+
protocol: json-rpc
297
+
enforcement: enforce
298
+
json_rpc:
299
+
max_body_bytes: 131072
300
+
rules:
301
+
- allow:
302
+
rpc_method: initialize
303
+
- allow:
304
+
rpc_method: tools/list
305
+
- allow:
306
+
rpc_method: tools/call
307
+
params:
308
+
name: read_status
309
+
- allow:
310
+
rpc_method: tools/call
311
+
params:
312
+
name: submit_report
313
+
arguments.scope: workspace/main
314
+
```
315
+
277
316
#### Deny Rule Objects
278
317
279
318
Blocks specific operations on endpoints that otherwise have broad access. Deny rules are evaluated after allow rules and take precedence: if a request matches any deny rule, it is blocked regardless of what the allow rules or access preset permit.
@@ -356,6 +395,33 @@ endpoints:
356
395
operation_name: Admin*
357
396
```
358
397
398
+
##### JSON-RPC Deny Rule (`protocol: json-rpc`)
399
+
400
+
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.
401
+
402
+
| Field | Type | Required | Description |
403
+
|---|---|---|---|
404
+
| `rpc_method` | string | Yes | JSON-RPC method name or glob to deny. |
405
+
| `params` | map | No | Params matchers keyed by flattened object-param path. Omit to deny every call matching `rpc_method`. Strings, numbers, and booleans are converted to strings; arrays, `null`, and non-object top-level params do not produce matcher keys. |
406
+
407
+
Example JSON-RPC deny rules:
408
+
409
+
```yaml showLineNumbers={false}
410
+
endpoints:
411
+
- host: mcp.example.com
412
+
port: 443
413
+
path: /mcp
414
+
protocol: json-rpc
415
+
enforcement: enforce
416
+
rules:
417
+
- allow:
418
+
rpc_method: tools/*
419
+
deny_rules:
420
+
- rpc_method: tools/call
421
+
params:
422
+
name: delete_resource
423
+
```
424
+
359
425
### Binary Object
360
426
361
427
Identifies an executable that is permitted to use the associated endpoints.
Copy file name to clipboardExpand all lines: docs/sandboxes/policies.mdx
+50-4Lines changed: 50 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -148,7 +148,7 @@ The following steps outline the hot-reload policy update workflow.
148
148
149
149
To inspect a stored sandbox-authored revision instead of the current effective policy, pass `--rev <version>`.
150
150
151
-
5. Edit the YAML: add or adjust `network_policies` entries, binaries, `access`, or `rules`.
151
+
5. Edit the YAML: add or adjust `network_policies` entries, binaries, `access`, `rules`, or protocol-specific matchers such as GraphQL operation fields and JSON-RPC `rpc_method` / `params` rules.
152
152
153
153
6. Push the updated policy when you need a full replacement. Exit codes: 0 = loaded, 1 = validation failed, 124 = timeout.
154
154
@@ -173,7 +173,7 @@ Use `openshell policy update` when you want to merge network policy changes into
173
173
- remove one endpoint or one named rule without rewriting the rest of the file.
174
174
- preview a merged result locally with `--dry-run` before you send it to the gateway.
175
175
176
-
Use `openshell policy set` instead when you want to replace the full policy, update static sections, or make broader edits that are easier to express in YAML.
176
+
Use `openshell policy set` instead when you want to replace the full policy, update static sections, or make broader edits that are easier to express in YAML. Use full YAML for GraphQL and JSON-RPC rule shapes.
177
177
178
178
### Update Commands
179
179
@@ -210,6 +210,7 @@ This is the practical difference:
210
210
Current constraints:
211
211
212
212
-`--add-allow` and `--add-deny` work on `protocol: rest` and `protocol: websocket` endpoints.
213
+
- GraphQL and JSON-RPC fine-grained rules require full policy YAML applied with `openshell policy set`.
213
214
-`--add-deny` requires the endpoint to already have an allow base, either an `access` preset or explicit allow `rules`.
214
215
-`protocol: sql` is not a practical incremental workflow today. OpenShell does not do full SQL parsing, and SQL enforcement is not meaningfully supported yet.
215
216
@@ -228,7 +229,7 @@ Each segment has a fixed meaning:
228
229
|`host`| Yes | Destination hostname. |
229
230
|`port`| Yes | Destination port, `1` through `65535`. |
230
231
|`access`| No | Access preset for L7 endpoints: `read-only`, `read-write`, or `full`. Incremental updates expand presets into protocol-specific method/path rules for REST and WebSocket endpoints. |
231
-
|`protocol`| No | L7 inspection mode: `rest`, `websocket`, or `sql`. `sql` is audit-only and not a recommended workflow today. |
232
+
|`protocol`| No | L7 inspection mode accepted by `openshell policy update`: `rest`, `websocket`, or `sql`. `sql` is audit-only and not a recommended workflow today. Full policy YAML also supports `graphql` and `json-rpc`. |
232
233
|`enforcement`| No | Enforcement mode for inspected traffic: `enforce` or `audit`. |
233
234
|`options`| No | Comma-separated endpoint options. Use `websocket-credential-rewrite` with `protocol: websocket` or REST compatibility endpoints that perform a WebSocket upgrade. Use `request-body-credential-rewrite` only with `protocol: rest`. |
234
235
@@ -548,7 +549,7 @@ For an end-to-end walkthrough that combines this policy with a GitHub credential
548
549
- { path: /usr/bin/gh }
549
550
```
550
551
551
-
Endpoints with `protocol: rest` enable HTTP request inspection and can opt in to supported text request body credential rewrite. Endpoints with `protocol: websocket` validate WebSocket upgrades and inspect client text messages on the upgraded request path. WebSocket endpoints can also classify GraphQL-over-WebSocket operation messages with the same operation rules used by GraphQL-over-HTTP. Endpoints with `protocol: graphql` parse GraphQL-over-HTTP payloads before evaluating rules. The endpoint-level `path` field lets these protocols share `api.github.com:443` without treating GraphQL payloads as plain REST `POST /graphql` requests.
552
+
Endpoints with `protocol: rest` enable HTTP request inspection and can opt in to supported text request body credential rewrite. Endpoints with `protocol: websocket` validate WebSocket upgrades and inspect client text messages on the upgraded request path. WebSocket endpoints can also classify GraphQL-over-WebSocket operation messages with the same operation rules used by GraphQL-over-HTTP. Endpoints with `protocol: graphql` parse GraphQL-over-HTTP payloads before evaluating rules. Endpoints with `protocol: json-rpc` parse JSON-RPC-over-HTTP request bodies and evaluate `rpc_method` and optional params rules. The endpoint-level `path` field lets these protocols share `api.github.com:443` without treating GraphQL payloads as plain REST `POST /graphql` requests.
552
553
</Tab>
553
554
554
555
</Tabs>
@@ -579,6 +580,51 @@ REST rules can also constrain query parameter values:
579
580
580
581
`query`matchers are case-sensitive and run on decoded values. If a request has duplicate keys (for example, `tag=a&tag=b`), every value for that key must match the configured glob(s).
581
582
583
+
### JSON-RPC matching
584
+
585
+
JSON-RPC endpoints use `protocol: json-rpc`. The proxy parses sandbox-to-server JSON-RPC-over-HTTP request bodies, evaluates the `method` field against `rpc_method`, and can match object params through dot-separated `params` keys.
586
+
587
+
JSON-RPC policy enforcement is directional. It applies to HTTP request bodies sent by the sandboxed process to the configured endpoint. JSON-RPC responses and server-to-client messages carried on response bodies or MCP SSE streams are relayed but are not currently parsed for policy enforcement.
588
+
589
+
JSON-RPC endpoint policies currently require full policy YAML applied with `openshell policy set`; the incremental `openshell policy update --add-endpoint` parser does not accept `json-rpc` as a protocol.
590
+
591
+
```yaml showLineNumbers={false}
592
+
mcp_server:
593
+
name: mcp_server
594
+
endpoints:
595
+
- host: mcp.example.com
596
+
port: 443
597
+
path: /mcp
598
+
protocol: json-rpc
599
+
enforcement: enforce
600
+
json_rpc:
601
+
max_body_bytes: 131072
602
+
rules:
603
+
- allow:
604
+
rpc_method: initialize
605
+
- allow:
606
+
rpc_method: tools/list
607
+
- allow:
608
+
rpc_method: tools/call
609
+
params:
610
+
name: read_status
611
+
- allow:
612
+
rpc_method: tools/call
613
+
params:
614
+
name: submit_report
615
+
arguments.scope: workspace/main
616
+
deny_rules:
617
+
- rpc_method: tools/call
618
+
params:
619
+
name: delete_resource
620
+
binaries:
621
+
- { path: /usr/bin/python3 }
622
+
```
623
+
624
+
`json_rpc.max_body_bytes`controls how many JSON-RPC-over-HTTP request body bytes OpenShell buffers for inspection. It defaults to `65536`.
625
+
626
+
`params` matchers are case-sensitive and use the same string glob or `{ any: [...] }` matcher syntax as REST query parameters. They match scalar leaf values from object params: strings, numbers, and booleans are converted to strings, and nested JSON object params are flattened with dot-separated keys before matching. Arrays, `null`, and non-object top-level params do not produce matcher keys. This is useful for controls such as matching MCP `tools/call` by `params.name`, but it is not a complete MCP payload policy for rich nested content. For batch requests, OpenShell evaluates each JSON-RPC call independently and denies the whole batch if any call is denied.
627
+
582
628
### GraphQL matching
583
629
584
630
GraphQL endpoints use `protocol: graphql`. The proxy parses GraphQL-over-HTTP `GET` and `POST` requests, classifies each operation, and evaluates rules against the operation type, optional operation name, and selected root fields.
0 commit comments