* feat(examples): add supervisor middleware content guard Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * docs(examples): refine middleware preview warning Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(examples): add middleware policy version Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * refactor(supervisor-middleware): simplify service endpoints Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(examples): adapt content guard to middleware enums Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(examples): align content guard with merged middleware Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * feat(examples): add content guard smoke flow Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * chore(examples): remove smoke launcher test Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(examples): align content guard smoke with main Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(examples): address content guard review feedback Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * refactor(examples): parse cargo metadata with jq Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(examples): prioritize longest content matches Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * docs(examples): use GitHub warning alert Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(examples): merge overlapping content matches Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * docs(examples): render preview warning on GitHub Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> --------- Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
Supervisor Middleware Content Guard
Warning
Supervisor middleware is a research preview. Its policy and service contracts may change without compatibility guarantees. Use it only to prototype and evaluate middleware integrations.
This example implements an operator-run supervisor middleware service. It scans UTF-8 HTTP request bodies for configured literal strings, then either replaces every match or denies the request. Findings report only aggregate counts and never include configured terms or request content.
Warning
This intentionally simple implementation demonstrates the supervisor middleware service contract. It is not a complete or reliable content guard and must not be used as a security control. It handles only UTF-8 request bodies and case-sensitive literal terms, merges overlapping literal match ranges before redaction, and does not address the encodings, transformations, normalization, streaming, or adversarial inputs that a production content guard must handle.
Prerequisites
Install cargo, curl, jq, and openssl on the host before running the smoke script.
Run the smoke example
Run the end-to-end smoke suite to build and start a local gateway, start the content-guard service, create a sandbox, and send the same request body to two destinations:
./examples/supervisor-middleware-content-guard/smoke.sh --test-suite
The first request goes to httpbin.org, which matches the middleware endpoint selector. The response contains [FILTERED] instead of prototype-secret. The second request goes to httpbingo.org, which is allowed by network policy but does not match the middleware selector. Its response contains the original prototype-secret value. The smoke suite asserts both results and cleans up the sandbox, gateway, and middleware processes.
Run the script without flags to leave the local stack running for interactive use:
./examples/supervisor-middleware-content-guard/smoke.sh
The script creates the sandbox and prints the guarded and unguarded request commands. Press Ctrl-C to clean up. The middleware service must be reachable from both the host gateway and sandbox containers. The script detects a non-loopback host address automatically; override it when necessary:
CONTENT_GUARD_SMOKE_HOST=192.168.1.10 ./examples/supervisor-middleware-content-guard/smoke.sh --test-suite
Run manually
Start the service before starting the gateway. Bind to all host interfaces so a local containerized gateway and sandbox supervisor can reach it:
cd examples/supervisor-middleware-content-guard
cargo run -- --bind 0.0.0.0:50051
Add the service registration to your local gateway TOML:
[[openshell.supervisor.middleware]]
name = "content-guard-example"
grpc_endpoint = "http://host.openshell.internal:50051"
max_body_bytes = 262144
timeout = "500ms"
The gateway calls Describe during startup and fails to start if the service is unavailable. Both the gateway and sandbox supervisors must resolve and reach the configured endpoint. Change the hostname when host.openshell.internal is not the shared host address for your local driver.
The http:// gRPC endpoint uses plaintext without peer authentication.
The service manifest describes its supported operation and phase. The policy attaches the complete service by the operator-owned content-guard-example registration name, not by the diagnostic manifest name.
The network_middlewares map key prototype-content-guard is the stable policy-local identity. The optional name field is a human-readable label, and order must be unique across every middleware config in the policy.
Apply the example policy
The included policy allows curl to POST to https://httpbin.org/anything and https://httpbingo.org/anything. Only httpbin.org matches the middleware selector, where the content guard replaces prototype-secret or internal-only in the request body:
openshell sandbox create --policy examples/supervisor-middleware-content-guard/policy.yaml
From the sandbox, send a matching request:
curl -sS https://httpbin.org/anything \
--header 'content-type: application/json' \
--data '{"note":"prototype-secret"}'
The echoed JSON body contains [FILTERED] instead of the configured term.
Configuration
| Field | Required | Description |
|---|---|---|
mode |
No | redact (default) replaces matches; deny rejects the request. |
terms |
Yes | Non-empty list of non-empty, case-sensitive literal strings. Overlapping match ranges are merged before redaction. |
replacement |
No | Replacement text for redact; defaults to [REDACTED] and is invalid with deny. |
To exercise denial, change the policy config to:
config:
mode: deny
terms:
- prototype-secret
The implementation supports only HttpRequest/pre_credentials, advertises a 256 KiB body limit, and inherits the service-wide RPC timeout. The gateway registration may set a smaller body limit. A binding can advertise a shorter timeout, but it cannot extend the operator-configured timeout.