Compliance gap analysis¶
CodeNavi's Claude Code plugin (v0.2.x and later) ships an evidence-linked compliance checker: /codenavi:compliance runs a rule-by-rule gap analysis of an indexed codebase against a compliance pack and writes a markdown report in which every verdict cites the exact code it was verified against.
What this is — and is not. The output is a gap analysis for audit preparation: a defensible starting inventory of where your code stands against a standard, with
file:lineevidence for every claim. It is not a certification, an audit, or legal advice, and the report says so on its face.
Packs¶
| Pack | Standard | Rules |
|---|---|---|
asvs-core |
OWASP ASVS 5.0 (core subset) | 30 rules across authentication, session management, access control, input handling, secrets, logging — each tagged with its official ASVS verification level (L1/L2) |
owasp-top10 |
OWASP Top 10 (2025) | 10 groups mapped to the official categories |
cra-annex1 |
EU Cyber Resilience Act — Regulation (EU) 2024/2847, Annex I | 20 rules: 14 over the Part I product requirements (2)(a)–(m) — one per item, with (d) split into authentication and authorization — plus the six Part II vulnerability-handling points that leave code evidence (SBOM, release record, security testing, disclosure, CVD policy, secure update distribution) |
Run /codenavi:compliance with no arguments to list the packs installed with your plugin version. The two OWASP-derived pack files are CC BY-SA 4.0 (adapted from OWASP material, © OWASP Foundation); the CRA pack paraphrases EU legislation with our own search recipes and is MIT, like the rest of the plugin.
The CRA pack¶
The Cyber Resilience Act binds manufacturers of products with digital elements placed on the EU market — installable, downloadable and on-prem software included. Pure SaaS is outside it unless it is remote data processing tied to such a product, and an agency that only hosts a client's web application is usually out of scope. The pack carries that caveat in its frontmatter and the report prints it under the header, so a CRA gap report never overclaims who it applies to. Whether a given codebase is a CRA "product" is a legal determination the tool does not make.
Two dates matter: Article 14 vulnerability and incident reporting has applied since 11 September 2026; the Annex I essential requirements apply from 11 December 2027.
What the pack checks, and what it deliberately does not:
- Part I (product properties) — thirteen requirements, one rule each, with the access-control item split into authentication and authorization, so 14 rules. About half re-use ASVS recipes (access control, authentication, cryptography, integrity, attack surface, secure defaults, logging). The rest are CRA-specific and new: a reset-to-secure-state path, security updates on by default with an opt-out and notification, data minimisation, availability and denial-of-service resilience, no negative impact on other networks, exploitation mitigation, a user opt-out for activity recording, and permanent removal of all user data and settings.
- Part II (vulnerability handling) — mostly process, so most of it is marked
cannot check from codeon purpose. The six points that leave code evidence are rules: a machine-readable SBOM, a release record that names security fixes, security testing wired into CI, public disclosure of fixed vulnerabilities, a coordinated-disclosure policy with a contact address, and signature-verified update distribution.
The report is an input to the manufacturer's Annex VII technical documentation and Annex V declaration of conformity. It is neither of those documents, and it is not a conformity assessment.
Dependency reachability¶
A dependency scanner tells you a package has a CVE. The CRA question — and the first question in any triage — is whether the product is exposed: does your code import that package, call the vulnerable function, and let untrusted input reach it? An SBOM cannot answer that. The index can, for your own code.
Ask the agent directly — "are we exposed to CVE-XXXX in package Y?" — with the compliance plugin installed, and it follows a fixed procedure from the compliance-check skill:
- Confirms the version in use from the lockfile or manifest, and says so if nothing pins it.
- Finds the import sites of the package with
grep_search. - Finds the call sites of the vulnerable symbol, then walks your own callers of each wrapper with
find_callers, and reads every site to see whether untrusted input reaches it. That is the difference between "linked" and "exploitable". - Sizes the remediation with
impact_analysison the wrapper — the blast radius of changing or removing the call. - Reports package and pinned version, import sites, verified call sites with
file:line, whether untrusted input reaches them, and the limits below. It can append this as a Dependency reachability section to a compliance report.
Limits, stated in every answer. The index holds your own source; vendor/, node_modules/ and similar trees are excluded by default (re-include a path with EXCLUDE_DIRS_DROP if you need it). So this is import-site reachability — not a transitive call-graph through the dependency tree. The call graph is name-based and unreliable on Perl, where grep results are authoritative. A "not reachable" answer means no path found by these searches, never "not exploitable".
How a run works¶
For each rule in the pack, the agent:
- Searches the index with targeted queries —
semantic_searchfor concepts,grep_search/symbol_searchfor known names — scoped to the target codebase. - Verifies candidate evidence by reading the actual source (
read_file); search hits alone are never cited. - Records a verdict:
pass,partial,fail,not applicable, orcannot check from code— with the reasoning and the verifiedfile:linecitations.
The report is written as codenavi-compliance-<pack>-<codebase>-<date>.md: a summary rollup up top, then one section per rule. It goes to the path you name, or the analyzed codebase's own root, or your working directory — the agent picks in that order and won't drop one project's findings into another project's repo.
Because asvs-core rules carry their ASVS level, the rollup also reports the Level 1 bar — ASVS Level 1: 9 of 19 applicable L1 rules pass — which is usually the number a customer, insurer, or auditor actually asks for. Levels come from the official ASVS 5.0 requirement data, not our own grading.
The header records the codebase revision the run was made against, so a later run can diff against it rather than re-litigate every rule. On a re-run the agent reads the previous report, re-verifies every rule the intervening commits touched plus everything that previously failed, and marks anything it carries forward — a stale verdict presented as current is worse than no report.
Honest verdicts are the point: rules a static check cannot decide (runtime configuration, operational process) are marked cannot check from code with the reason — not guessed.
Security posture¶
- Chunks the scanner flagged (
[FLAGGED:…]) or secret-redacted ([REDACTED:…]) never count as passing evidence. PII redactions ([REDACTED:pii_…]) are the exception: they are data minimization, not a threat, and don't disqualify a chunk. - Secret-like strings from your code are never reproduced in the report.
- The analysis runs inside your coding agent: retrieved code goes only where your agent already sends code. Nothing is uploaded anywhere else, and the CodeNavi server itself makes no outbound calls for this feature.
Beyond OWASP: framework fit¶
The checker's packs are OWASP-based, but compliance conversations usually span more — GDPR, SOC 2, ISO 27001, HIPAA, PCI DSS, FedRAMP. CodeNavi's contribution to those is architectural (self-hosted, zero egress by default) rather than a pack: the security model has the framework-by-framework mapping.
Sample reports¶
Two complete owasp-top10 runs against public codebases, published as they came out of the checker (one note trimmed in the Bugzilla report to avoid publishing an attack recipe):
| Sample | Target | Result |
|---|---|---|
| OWASP Top 10 vs Bugzilla | Bugzilla 5.x, Perl/CGI, ~290 files | 0 pass · 7 partial · 3 fail |
| OWASP Top 10 vs Laravel | laravel/framework 13.x, PHP library |
2 pass · 8 partial · 0 fail |
Both are demonstration runs against public source used as a testbed, not security assessments of those projects. The raw files with their integrity footers are under /samples/ (Bugzilla, Laravel; each also has a .txt twin for viewing inline).
Running it¶
/codenavi:compliance asvs-core
/codenavi:compliance owasp-top10 --codebase myapp
/codenavi:compliance cra-annex1 --codebase myproduct
Leave --codebase off on a single-codebase install. Pass a path as a further argument to choose where the report is written; otherwise it lands in the analysed codebase's root.
What to do with the result:
- Read the summary line, then the
partialandfailrows. Each cites the file and lines the verdict was verified against, so the fix and the evidence are in the same row. - Treat the "Not checkable from code" list as your process to-do. Those rules name where the evidence lives instead, usually a policy, a runbook, or an operational setting. For the CRA pack that list is most of Annex I Part II, and it is the input to the manufacturer's technical documentation.
- Re-run after the fixes. The header records the revision the run was made against. On a re-run the agent reads the previous report, re-verifies every rule the intervening commits touched plus everything that failed, and marks anything carried forward, so a fixed gap never shows as still open.
- Keep the footer. The last line is a self-hash. Any edit after it invalidates it; verify with
head -n -1 <report>.md | sha256sum.
To ask about one dependency vulnerability rather than run a whole pack, just ask in a normal session, for example "are we exposed to CVE-2026-1234 in the requests package?" — see Dependency reachability. No slash command is needed; the skill triggers on the question.
Expect a full asvs-core run to take 20–40 minutes on a warm index — searches run sequentially by design (they serialize on the GPU). The command tells you this up front and reports progress per rule.
Requirements: the CodeNavi Claude Code plugin ≥ 0.2.1 (≥ 0.5.13 for the CRA pack and dependency reachability) (see Claude Code integration) and an indexed codebase (see the setup guide).