Governance packs are curated, versioned OPA policy bundles that map your sandboxes to a security framework’s controls. Enable a pack with a single policy_ref and every matching action your agent takes is gated at the declaw enforcement layer — with the framework’s control IDs recorded on each denial for audit-ready evidence.
Packs build on declaw’s non-bypassable platform floor (which already blocks living-off-the-land commands, kernel-module loading, cloud-metadata/IMDS access, and metadata egress). A pack adds denials and attaches framework control IDs; it can only tighten policy, never relax it.
Available packs
Pack (policy_ref) | Framework |
|---|
baseline-hardening@v1 | Declaw baseline (reverse-shell / remote-shell tooling) |
owasp-llm-top10@v1 | OWASP Top 10 for LLM Applications (2025) |
owasp-agentic@v1 | OWASP Top 10 for Agentic Applications (ASI) |
owasp-mcp@v1 | OWASP MCP Top 10 |
eu-ai-act@v1 | EU AI Act — Regulation (EU) 2024/1689 |
nist-ai-rmf@v1 | NIST AI RMF 1.0 + Generative AI Profile |
iso-42001@v1 | ISO/IEC 42001:2023 (AI Management System) |
mitre-atlas@v1 | MITRE ATLAS (adversarial ML threats) |
csa-aicm@v1 | CSA AI Controls Matrix (AICM) v1.0 |
Browse the live catalog (each pack’s enforces vs advisory controls, gates, and description):
curl https://api.declaw.ai/governance/packs
Honest by design. Each pack distinguishes the controls it actually enforces (a real policy rule that fires a denial) from controls it can only mark advisory (a framework requirement with no runtime signal at the sandbox layer — e.g. organizational process, human-in-the-loop approval, or response-body inspection). A pack never claims a control it can’t enforce. Governance packs are an enforcement + evidence tool, not a legal conformity assessment.
Enable a pack
Per sandbox (SDK)
Reference a pack in the sandbox’s custom_policy:
from declaw import Sandbox, SecurityPolicy, CustomPolicyConfig
sandbox = Sandbox.create(
security=SecurityPolicy(
custom_policy=CustomPolicyConfig(
enabled=True,
policy_ref="owasp-llm-top10@v1",
),
),
)
Account-wide floor (admin)
Apply a pack as a non-bypassable floor on every sandbox an account creates — no per-sandbox change required:
curl -X POST https://api.declaw.ai/admin/accounts/<account_id>/policy \
-H "X-Admin-Secret: $ADMIN_SECRET" \
-d '{ "policy_ref": "owasp-llm-top10@v1", "enabled": true }'
Stacking multiple frameworks
To enforce several frameworks at once, publish a composite bundle (the concatenation of the member packs — denials are additive and tighten-only) and point a single policy_ref at it. Composites are published through the same bundle endpoint and referenced exactly like a single pack.
Model / endpoint allowlists
Some controls (OWASP LLM03 supply-chain, ASI02 tool misuse) need to see the model an agent calls. Opt a sandbox into the content gate so a model-allowlist rule runs on LLM egress even without an ML scanner enabled:
SecurityPolicy(
content_gate={"enabled": True, "domains": ["api.openai.com", "api.anthropic.com"]},
custom_policy=CustomPolicyConfig(enabled=True, policy_ref="owasp-llm-top10@v1"),
)
The model is read from the (decrypted) request body and exposed to your policy as input.attributes.model.
Compliance evidence
Every denial a pack produces records the framework control IDs it satisfies (from the rule’s metadata) into the audit log. Pull the per-account compliance report — enabled packs plus denials grouped by control, framework, and gate over a window:
curl "https://api.declaw.ai/admin/accounts/<account_id>/compliance?start=<ISO>&end=<ISO>" \
-H "X-Admin-Secret: $ADMIN_SECRET"
{
"enabled_packs": { "account_policy": { "policy_ref": "owasp-llm-top10@v1", "enabled": true } },
"denials_by_control": [ { "control": "OWASP-LLM06-ExcessiveAgency", "count": 42 } ],
"denials_by_framework": [ { "framework": "OWASP", "count": 51 } ],
"denials_by_gate": [ { "category": "command", "event": "command_denied", "count": 12 } ]
}
The same data renders in the console under Admin → Accounts → Compliance.
How it works
A pack is a set of OPA Rego modules — one per enforcement gate it touches:
| Gate | What it governs | Example pack control |
|---|
cmd.exec | every command the agent (or a sub-agent) runs | reverse-shell tooling → OWASP-ASI02 |
net.egress | every outbound connection | IMDS/metadata SSRF → OWASP-LLM02 |
content.scan | the request body on LLM egress (model, injection findings) | high-confidence prompt injection → OWASP-LLM01 |
sandbox.create | provisioning (tier, template, features) | feature gating → NIST-AC-3 |
Because the agent runs inside the declaw microVM, these gates aren’t advisory — they are the only path the agent’s actions can take. See Network Policies and the security overview for the underlying enforcement model.
How policy_ref is resolved
A policy_ref takes one of three forms, all resolving against declaw-controlled storage only (no arbitrary URL fetch):
| Form | Scope |
|---|
name@version (e.g. owasp-llm-top10@v1) | account-scoped — looked up in the registry keyed by your account, with a shared platform fallback for the built-in packs. This is where per-tenant isolation lives. |
sha256:<hex> | content-addressed, global — fetches the object whose content hashes to <hex>. |
blob:<key> | global — a raw object under the bucket’s policies/ namespace. |
Security model. The sha256: and blob: forms are intentionally content-addressed-global: they ignore the account and read any object in the (dedicated, non-tenant-writable) policy bucket, because shared platform packs and content-addressed dedupe require global reads. Confidentiality of policy text under these forms rests on hash opacity, not access control, and hashes are not secrets. For per-account isolation, use name@version refs; don’t place tenant-confidential policy in the shared bucket expecting per-tenant read scoping. Path traversal and namespace escape are blocked, and resolved policy is never echoed back to the agent.