policy_ref. When you need rules specific to your threat model — a command denylist, an egress allowlist, a model allowlist — you can author them yourself in OPA Rego and attach them to a sandbox with CustomPolicyConfig.
Your rules are additive to declaw’s non-bypassable platform floor (which already blocks living-off-the-land commands, kernel-module loading, device/storage operations, and cloud-metadata/IMDS access). You write deny rules that tighten policy; you can never relax a platform default.
The six gates
Declaw evaluates Rego at six enforcement gates. Each gate is its own Rego package — write your rules in the package that matches the action you want to govern:
The gates also enforce differently, which matters when you test:
cmddeny → the command is rejected before it runs (surfaces as an HTTP 403 / raised exception, not a non-zero exit code).networkdeny → the command runs, but the outbound connection is dropped at the proxy (e.g.curlexits non-zero with a reset/timeout — there is no 403).
The deny-only model
You only ever writedeny rules:
deny is a partial set, and partial-set rules are additive across modules — so your denials compose with the platform defaults (and with each other) without ever being able to remove a platform denial.
CustomPolicyConfig
inline_rego, inline_modules, and policy_ref can be combined — all sources are concatenated with the platform defaults before evaluation. Use inline_rego for the single-package case and inline_modules when your policy spans gates.Worked examples
Allowlists with a deny-only engine
Since you can only writedeny rules, an allowlist is expressed as “deny anything not in the approved set”. Combine it with default_deny=True so an evaluator fault also blocks:
glob.match for wildcard domains:
Input schema per gate
Each gate evaluates your rules against aninput document. The key fields:
Every gate also receives a shared context block:
input.context.tier, input.context.account_id, input.context.sandbox_id, and input.context.template. Use it to scope a rule, e.g. forbid interactive shells on a locked-down tier:
Content gate
The content gate (declaw.platform.content) sees the decrypted LLM request body — the model name and the ML scanner’s findings — so you can enforce a model allowlist or write cross-signal rules that combine multiple scan results.
This gate runs inside the body-scanning path, so by default it only fires when a scanner is already intercepting that domain. To run a model-allowlist rule without enabling an ML scanner, opt the sandbox in with ContentGateConfig and list the LLM API hosts to intercept:
input.attributes.model. Rule A and Rule B are independent — either firing blocks the request before it reaches the upstream LLM.
Content-gate caveats. The gate is only evaluated when the connection is intercepted — either by an active ML scanner on the domain or by an explicit
ContentGateConfig entry for that host (per-destination network rules are unaffected; that gate always runs). Also, scan_results.pii.count reflects whole-body (non-JSON) text; for JSON LLM bodies, value-level PII is scanned and redacted separately, so don’t gate on pii.count for JSON traffic.Testing and fail-closed behavior
Your inline Rego is compile-checked at sandbox create. If a module fails to parse or compile (a syntax error, a redeclareddefault allow, an unknown built-in), the create request fails with an error describing the problem — invalid policy never reaches a running sandbox.
At runtime, default_deny controls what happens if the evaluator itself errors (engine unreachable, evaluation timeout):
default_deny=True(fail-closed) — an evaluator error denies the action. Recommended for any hard security gate (denylists, allowlists, model gating).default_deny=False(fail-open) — the action is allowed on evaluator error. Acceptable only for advisory rules where availability outweighs the missed check.
cmd-gate denial surfaces as a 403 / raised exception, while a network-gate denial lets the command run but drops the connection (use a resolvable host so the test exercises the gate and not a DNS failure).
Next steps
- Governance packs — curated, framework-aligned policy (OWASP, NIST, EU AI Act, and more) you enable with a single
policy_ref, with per-denial compliance evidence. - Policy bundles — publish your own modules as a versioned, reusable bundle and reference it by
name@version,sha256:, orblob:instead of inlining the Rego on every sandbox. - Network policies — the domain-allowlist / IP-CIDR layer that runs alongside the
networkgate.