Skip to content

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:2025LLM10: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.)

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.

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.

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/>(&lt;class&gt;__remediation__)"]
    D --> R["Policy Catalog<br/>review → dry-run → apply"]
    R --> E["Enforced"]
    E -->|"re-score"| C
  1. Read the matrix for a namespace, filtered to Gaps (worst-first by priority).
  2. 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.
  3. Norviq builds a dry-run remediation draft (details below) and drops it in the Policies → Catalog inbox, deep-linking you straight to it.
  4. 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.
  5. The next coverage read re-scores the control as enforced.

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.

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.

  • 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.

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}
Terminal window
# 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 JSON
curl -s "$NRVQ_API_URL/api/v1/compliance/owasp/export?namespace=chatbot-prod&format=json" \
-H "Authorization: Bearer $NRVQ_API_TOKEN"

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.