Compliance & coverage
The Compliance page answers a question an auditor actually asks: for a recognized threat framework, which techniques does your running policy actually enforce — and where are the gaps? Norviq maps every framework technique to the concrete Rego rules that would block it, checks those rules against the policy currently loaded for a namespace, and shows you a live coverage matrix, the gaps, and a one-click path from a gap to a generated remediation policy.
Two frameworks are live:
| Framework | Display | Control IDs |
|---|---|---|
atlas |
MITRE ATLAS | AML.T0051, AML.T0049, … |
owasp |
OWASP LLM Top 10 (2025) | LLM01:2025 … LLM10:2025 |
(Other frameworks — OWASP Agentic, NIST AI RMF, ISO/IEC 42001, EU AI Act — appear as roadmap rows with no coverage numbers, so they’re never mistaken for live scoring.)
How coverage is judged
Section titled “How coverage is judged”Coverage is evidence-based, not a checkbox. Each framework control maps to a set of Norviq
rule IDs (llm01_prompt_injection, deny_sql_injection, …). A control is judged against the
Rego actually loaded for the selected namespace (plus the cluster baseline):
- Enforced — the control is in scope for a runtime tool-call PEP and at least one of its mapped rules is present in a loaded, enforcing policy.
- Gap — in scope, but no mapped rule is loaded. This is what remediation targets.
- Out of scope — the technique isn’t something a runtime tool-call enforcement point can address (model-training poisoning, embedding weaknesses, misinformation). Out-of-scope controls are excluded from the coverage denominator — you’re scored on what Norviq can actually enforce, never penalized for a control no PEP could cover.
Coverage % = enforced ÷ (enforceable total), per namespace. Each control row also shows the real observed / blocked counts for its rules and the affected agent classes (clickable through to the Audit Log and Agents views), so “enforced” is always backed by traffic, not just a rule’s presence.
What each framework enforces today
Section titled “What each framework enforces today”The in-scope controls and the rules that satisfy them:
MITRE ATLAS
| Technique | Enforced by |
|---|---|
AML.T0051 LLM Prompt Injection |
llm01_prompt_injection |
AML.T0054 LLM Jailbreak |
deny_shell_execution, llm01_prompt_injection |
AML.T0057 LLM Data Leakage |
llm02_data_leakage, base64_decoded_threat |
AML.T0053 LLM Plugin Compromise |
llm05_supply_chain, llm06_excessive_agency |
AML.T0050 Command & Scripting Interpreter |
deny_shell_execution |
AML.T0049 Exploit Public-Facing Application |
deny_sql_injection |
AML.T0012 Valid Accounts |
cross_tenant_access |
OWASP LLM Top 10 (2025)
| Control | Enforced by |
|---|---|
LLM01:2025 Prompt Injection |
llm01_prompt_injection |
LLM02:2025 Sensitive Information Disclosure |
llm02_data_leakage, base64_decoded_threat |
LLM05:2025 Improper Output Handling |
deny_sql_injection, base64_decoded_threat |
LLM06:2025 Excessive Agency |
llm06_excessive_agency, deny_shell_execution |
A few in-scope controls (e.g. ATLAS AML.T0055 Unsecured Credentials, OWASP LLM07:2025 System
Prompt Leakage, LLM10:2025 Unbounded Consumption) have no shipped runtime rule template.
Norviq does not fake coverage for them — asking it to remediate one returns an escalate
result telling you it needs a bespoke control, never a hollow deny-all. The
strict preset / comprehensive.rego baseline already carries every rule in the tables above, so
a namespace running strict scores high out of the box; gaps appear when a class runs a narrower
custom or preset policy.
Finding and closing a gap
Section titled “Finding and closing a gap”The workflow, end to end:
flowchart LR
C["Coverage matrix<br/>(per namespace)"] --> G["Gap<br/>(in scope, no rule loaded)"]
G -->|"Generate enforcing policy"| D["Remediation draft<br/>(<class>__remediation__)"]
D --> R["Policy Catalog<br/>review → dry-run → apply"]
R --> E["Enforced"]
E -->|"re-score"| C
- Read the matrix for a namespace, filtered to Gaps (worst-first by priority).
- Pick a gap and click Generate enforcing policy — or check several gaps and Generate for selected as a batch, choosing whether it targets this affected class, all affected classes, or a specific one.
- Norviq builds a dry-run remediation draft (details below) and drops it in the Policies → Catalog inbox, deep-linking you straight to it.
- Review & apply in the Catalog runs the draft through the standard gated policy editor (review → optional dry-run → Confirm apply). Nothing enforces until you apply.
- The next coverage read re-scores the control as enforced.
What the generated policy is
Section titled “What the generated policy is”generate_remediation_rego produces a default-allow module,
package norviq.remediation.<framework>.<control_id>, scoped to one agent class
(input.agent.agent_class == "<class>"). For each mapped rule that has a runtime template it adds
one tighten-only blocks[...] clause — the same detections comprehensive.rego uses:
| Rule | Blocks |
|---|---|
deny_sql_injection |
execute_sql carrying OR 1=1 / DROP TABLE / UNION SELECT / ; -- / ' OR ' |
deny_shell_execution |
shell metacharacters (;, &&, $(, `, |) in params |
llm01_prompt_injection |
“ignore previous instructions” / “system prompt”-style overrides |
llm02_data_leakage |
secret-read tools (read_env, get_secret, …) |
llm05_supply_chain |
plugin/code-load tools (load_plugin, download_script, eval, …) |
llm06_excessive_agency |
destructive tools (delete_record, drop_table, truncate) |
cross_tenant_access |
a tenant_id/namespace param that isn’t the caller’s own |
base64_decoded_threat |
base64-obfuscated payloads carrying any of the above |
Because it’s applied to the dedicated <class>__remediation__ overlay key — never the class’s
base policy — it can only add the blocks that close the gap; the class’s own comprehensive or
custom policy is never overwritten. It’s tighten-only at overlay priority (see
Writing policies §3). Generation is
admin-only, and the draft lands in the same intent_drafts inbox as the Attack Graph’s drafts
— which the evaluator never reads, so a draft can never auto-enforce.
The audit-evidence pack
Section titled “The audit-evidence pack”Export audit-evidence pack produces a point-in-time attestation for an auditor — per control: scope, status, mapped vs enforcing policies, and the real observed/blocked counts over the range, plus the headline coverage %. Available as machine-readable JSON or a dependency-free single-page PDF, minted in-cluster with no egress.
The pack counts real traffic only. Red-team framework events and synthetic/probe/eval identities are excluded from the observed/blocked headline — an evidence pack must not read as enforcement proof when the “traffic” was your own test harness. The excluded count is surfaced explicitly (“Real traffic only · N synthetic/simulated events excluded”), so the exclusion is visible rather than hidden. Red-team efficacy lives on its own clearly-labeled surface (the red-team suite), never merged into these counts.
Coverage over time & efficacy
Section titled “Coverage over time & efficacy”- Trend — each coverage read records an hourly snapshot per (namespace, framework), so the page can sparkline coverage % and blocks over the selected range (needs ≥2 points; it shows an honest empty state otherwise, not a fabricated line).
- Efficacy banner — coverage tells you a rule is present; it doesn’t prove the rule works. The page overlays your last Red Team run’s proven-blocking percentage so the two are never confused. Rules-present is coverage; caught-in-practice is efficacy — prove the second with the red-team suite.
API reference
Section titled “API reference”All under /api/v1, bearer-token auth, namespace-scoped; the framework path segment is atlas
or owasp. Generation is admin-only.
| Method & path | Purpose |
|---|---|
GET /compliance/{framework}/coverage?namespace=<ns>&range=24h |
the coverage matrix — per-control status, covered/observed/blocked, coverage % |
GET /compliance/{framework}/trend?namespace=<ns>&range=30d |
coverage % + blocks over time |
GET /compliance/{framework}/export?namespace=<ns>&format=json|pdf |
the audit-evidence pack (real traffic only) |
POST /compliance/{framework}/generate |
admin — draft a remediation policy for one gap {technique_id, namespace, agent_class?} |
POST /compliance/{framework}/generate-batch |
admin — draft for several gaps {technique_ids[], namespace, class_mode} |
# where does the atlas coverage stand for a namespace?curl -s "$NRVQ_API_URL/api/v1/compliance/atlas/coverage?namespace=chatbot-prod" \ -H "Authorization: Bearer $NRVQ_API_TOKEN"
# export the evidence pack as JSONcurl -s "$NRVQ_API_URL/api/v1/compliance/owasp/export?namespace=chatbot-prod&format=json" \ -H "Authorization: Bearer $NRVQ_API_TOKEN"Where this fits
Section titled “Where this fits”The asset & attack graphs tell you what an agent can reach; compliance tells you how your enforced policy maps to a recognized framework. Both feed the same gated draft → review → apply loop in the Policy Catalog, and both are honest about the difference between a rule being present and a threat being proven blocked — which you close with the red-team suite. A practical order: run strict to cover the baseline, read the Compliance matrix for residual gaps, generate remediation for the ones that matter, apply, then export the evidence pack.