feat(policy): add JSONPath predicates for REST request bodies
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 8.7k
- Forks
- 1.3k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 253
Description
Problem Statement
OpenShell REST L7 policy can restrict by host, port, binary, HTTP method, path, and query parameters. Some REST APIs put the security-relevant authorization target inside the JSON request body, so path/query policy cannot express the intended least-privilege rule.
Example: Microsoft Graph sendMail is a REST call, not GraphQL:
POST https://graph.microsoft.com/v1.0/users/agent-mailbox@example.com/sendMail
Content-Type: application/json
The path identifies the sending mailbox, but the allowed recipient is only in the request body. With current REST L7 rules, policy can allow or deny the entire sendMail endpoint, but cannot express: allow this tool to send email only to allowed-recipient@example.com, with no cc/bcc recipients.
Proposed Design
Allow protocol: rest rules to include JSONPath predicates over the request body, evaluated fail-closed before forwarding upstream.
Example desired policy:
network_policies:
outlook_send_self:
name: outlook-send-self
endpoints:
- host: graph.microsoft.com
port: 443
protocol: rest
enforcement: enforce
rules:
- allow:
method: POST
path: /v1.0/users/agent-mailbox@example.com/sendMail
json_body:
max_bytes: 262144
assertions:
- selector: $.message.toRecipients[*].emailAddress.address
op: all_equal_ci
value: allowed-recipient@example.com
- selector: $.message.toRecipients
op: length_eq
value: 1
- selector: $.message.ccRecipients
op: empty_or_absent
- selector: $.message.bccRecipients
op: empty_or_absent
binaries:
- path: /usr/local/bin/outlook-send-self-email
Example Microsoft Graph payload:
{
"message": {
"subject": "Poem about DGX Spark",
"body": {
"contentType": "Text",
"content": "DGX Spark wakes with silicon light,\nA desk-side star for models in flight.\nThrough tensors bright and memory wide,\nIt keeps tomorrow close beside."
},
"toRecipients": [
{
"emailAddress": {
"address": "allowed-recipient@example.com"
}
}
],
"ccRecipients": [],
"bccRecipients": []
},
"saveToSentItems": true
}
Required semantics:
- Apply only to JSON request bodies.
- Fail closed if the body is missing, malformed, too large, or cannot be evaluated.
- Do not log request body contents or selected values.
- Deny rules should continue to take precedence over allow rules.
- Deny responses should identify which assertion failed without leaking body data.
Alternatives Considered
This is related to #1272. The content_filters proposal there is more flexible and could solve this use case by running a supervisor-side filter script over the request body.
The request here is for a simpler declarative policy UX for common structured JSON API cases. JSONPath predicates would be enough for this example, but either approach would unblock the underlying need: allow or deny REST requests based on fields inside the JSON body.
One workaround we found is to put the recipient validation in a dedicated precompiled helper tool, then use OpenShell policy to restrict the sensitive endpoint so only that tool can call it.
Agent Investigation
- Reviewed the current policy schema: REST L7 rules support method, path, and query matching; GraphQL rules support operation type/name/fields; request body credential rewrite is for placeholder substitution, not arbitrary JSON allow/deny predicates.
- Confirmed Microsoft Graph
sendMailis a REST endpoint with recipient information inside the JSON body, not a GraphQL operation payload. - Reviewed existing related issues: #1272 covers general scriptable content filters, #1022 covered GraphQL-specific body inspection, and #459 covered request-body credential placeholder rewriting.
Checklist
- I've reviewed existing issues and the architecture docs
- This is a design proposal, not a "please build this" request
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the current policy schema and architecture docs, then inspect the related proposals in #1272, #1022, and #459. The issue is a design proposal rather than an implementation task; completion would require an agreed declarative JSONPath predicate design covering fail-closed evaluation, precedence, size limits, and safe denial reporting.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100