Pro Edition — For Security Professionals

Rank by exploitation,
not by CVSS.

CVE matching, MITRE ATT&CK technique annotations, and composite risk scoring — with exploit-first ranking so the findings that are being exploited come first. Then send the result: one command renders a finished scan into a self-contained, print-ready HTML report that opens with no external network reference.

Annual Monthly Save 20%
$39/mo
Billed as $470/yr · saves $118 vs monthly
Subscribe Annual — $470/yr →
Cancel anytime; an annual plan stays active to the end of its paid year. · Compare all plans · Need Enterprise?

One file. No network. Hand it to the client.

A scan ends with a directory of artifacts. An engagement ends with something a client reads. nsauditor-ai report closes that gap: point it at a finished run and it renders an executive HTML report — one self-contained, print-ready file that opens with no external network reference of any kind. It survives an email attachment, a laptop with no connectivity, and a reviewer’s locked-down browser.

Add --brand when the report goes out under your own name and the cover page carries it. --format jira writes a Jira-importer CSV instead, so a findings list becomes a backlog. ⚠️ That CSV is written for Jira’s own CSV importer — the field mapping is done inside Jira, and this is not a live-instance integration we have verified.

What goes inside brand.json

Every field is optional. Omit the file and the report renders unbranded under its default title.

// brand.json — put it next to your logo
{
  "title":        "Q3 External Perimeter Review",
  "companyName":  "Acme Manufacturing GmbH",
  "preparedBy":   "J. Rivera, Security Consulting LLC",
  "contact":      "security@example.com",
  "logoPath":     "acme-logo.png"
}

title replaces the headline; companyName is who the report is for; preparedBy is who prepared it. logoPath is a local PNG or JPEG, resolved next to the brand file and embedded into the HTML as a data URI.

That logo rule is strict on purpose, and every part of it protects the same promise — that the file opens with no external network reference. A URL is refused and never fetched: a remote logo is egress at render time and a tracking pixel every time your client opens the report. SVG is refused, because SVG is markup that can carry a script and break the no-script guarantee from inside the image. The path may not escape the brand file’s own directory, checked as typed and again after symlinks resolve. The cap is 2 MB, and the format is read from the file’s magic bytes rather than its extension — renaming an SVG to .png does not get it past the check. A brand file that cannot be read, is not valid JSON, or whose logo is refused is a fatal error and no report is written: a flag you passed is never silently dropped, because that is how a report goes out unbranded without anyone noticing.

It states what it could not read

A report that quietly skips a container reads exactly like a report that had nothing to skip. So every report carries a container census: where finding-like records sit in a place the report does not read, that place is named and counted on the page. Silence is disclosed — never rendered as absence.

report is a Pro capability and is included in Enterprise. It produces no PDF: the HTML is print-ready, and your browser prints it when a PDF is what the client asked for.

report --format executive
→ one self-contained .html
→ zero external references
→ SENDABLE ✓
report --format jira
→ Jira-importer CSV
→ you map the fields in Jira
→ BACKLOG-READY
Records the report does not read
→ container named and counted
→ printed on the page itself
→ DISCLOSED, NOT DROPPED
Scan once — then render the thing you actually send
# 1 · a normal scan, as always
nsauditor-ai scan --host 192.168.1.0/24 --plugins all

# 2 · turn that finished run into the document you send
nsauditor-ai report --from out/192.168.1.0_<timestamp> --format executive

# or the same run as a Jira-importer CSV — you map the fields in Jira
nsauditor-ai report --from out/192.168.1.0_<timestamp> --format jira

Requires nsauditor-ai v0.2.49+ alongside your Pro or Enterprise licence. The report reads a run that already finished — it never re-scans, and it never reaches the network to render.

A worked engagement, licence to sent file

A consulting firm audits a client’s gateway at 192.168.1.1 and has to hand back something the client can actually read. Six steps — the same six on a /24, on a cloud account, or on a hundred hosts.

1 · Confirm the tier — and get authorization in writing
nsauditor-ai license --status

# On Community, `report` refuses at exit 2 and writes no file:
#   "`report` is a Pro capability. Your licence resolves to tier "community".
#    No file has been written."

# The other precondition is not a command: signed authorization for the
# target range. The scope on that letter is what the report cover should match.
2 · Build the brand kit once — the logo lives next to the JSON
~/consulting/brand/
├── brand.json
└── acme-logo.png

# The logo must sit inside this directory and be named by a plain relative
# path. Checked as typed, and again after symlinks resolve.
3 · Scan into a directory that belongs to this engagement
nsauditor-ai scan --host 192.168.1.1 --plugins all \
    --compliance all --out ~/engagements/acme-2026-09/

# Writes a run record `scan_run_<id>.json` at the root and a timestamped
# evidence folder beside it, with a .sha256 sidecar per artifact.

# One --out per engagement. `report` picks the NEWEST run in a directory and
# only refuses on an exact start-time tie — so a directory holding two
# engagements can render the wrong one silently. Name the run when in doubt.
4 · Render the deliverable, under your own name
# --run names YOUR OWN run — the id your scan printed. It is the <id> in the
# scan_run_<id>.json at the --out root. The one below is an example.
nsauditor-ai report --from ~/engagements/acme-2026-09/ \
    --run 20260904T184352Z-d9d796 \
    --format executive \
    --brand ~/consulting/brand/brand.json \
    --out ~/engagements/acme-2026-09/Acme_192.168.1.1_executive.html

[report] runId 20260904T184352Z-d9d796 · started 2026-09-04T18:43:52.970Z
[report] wrote ~/engagements/acme-2026-09/Acme_192.168.1.1_executive.html
 exit 0

# Without --out it writes report_<runId>.html beside the run record — inside
# your evidence tree, named after an id no client recognises. Name it for them.
5 · Render the remediation list for the client’s own tracker
nsauditor-ai report --from ~/engagements/acme-2026-09/ \
    --run 20260904T184352Z-d9d796 \
    --format jira \
    --out ~/engagements/acme-2026-09/Acme_192.168.1.1_findings.csv

# Summary,Description,Priority,Labels,External ID — one row per finding.
# Passing controls are filtered out; nobody wants a ticket for a PASS.
# External ID is stable, so a re-test maps back to the same rows.
# ⚠ The column-to-field mapping is done inside Jira's own CSV importer.
#   That is not a live-instance integration we have verified.
6 · Read the two channels before the file leaves your machine
# (a) A container census runs on load. If finding-like records sit somewhere
#     the report does not read, you are told — by container, with a count:
[report] WARNING: N finding-like object(s) on host <h> live in `<container>`,
         which this report does not read. They are NOT in the output.

# (b) Coverage caveats print too, and each is independent of the other:
[report] coverage: partial — N of M not scanned
[report] coverage: incomplete — the run did not record completion

# (c) Then open it. A self-contained file with no external reference looks
#     the same offline as online — which is the first thing the client's own
#     security team will check.

Send the HTML on its own. It is one file — no asset folder, no stylesheet to lose, and it prints from the browser when the client asked for a PDF. What you keep is the evidence directory and its .sha256 sidecars: that is what lets you show, months later, that the report you sent came from that scan. Re-rendering the same --run overwrites the same filename rather than accumulating copies, so there is never a question of which one is current.

Prioritize by exploitation, not by CVSS

Version-based CVE matching is just the start. Every finding is scored — CVSS weighted by verification status, with an uplift for findings carrying an initial-access technique — and the queue is then ordered exploit-first. Findings are emitted unverified — you adjudicate what stays, not the scanner.

OPEN
In the queue
Finding: TLS 1.0 on port 443
→ CVSS 7.4 → 0.74
→ UNVERIFIED ×0.6 → 0.44
→ RANKED — scored, then ordered
Finding: Default SNMP community 'public'
→ CVSS 9.8 → 0.98, UNVERIFIED ×0.6
→ initial-access technique +15% → 0.68
→ RANKED — uplift applied
Finding: Anonymous FTP (sanctioned host)
→ CVSS 7.5 → 0.75, UNVERIFIED ×0.6
→ no initial-access technique → no uplift
→ RANKED — below the two above it
Finding: CVE-2024-XXXX on legacy appliance
→ CVSS 6.1 → 0.61, UNVERIFIED ×0.6
→ not in CISA KEV → no exploit uplift
→ RANKED — below the exploited ones

A KEV-listed MEDIUM outranks an unexploited CRITICAL

Severity ranks how bad a vulnerability would be if it were exploited. It cannot tell you whether anyone is exploiting it. Pro closes that gap at scan time: every finding carrying a CVE is joined by CVE ID against a local CISA KEV catalog and a local FIRST EPSS scores file, then banded and reordered exploit-first.

The justification travels with the finding — the KEV flag, the EPSS score with its percentile, the CVE ids that matched, and the store’s own as-of date. Your ranking is always something you can date and defend. Both catalogs are free, public and operator-supplied: point Pro at files you control and the join runs entirely on your machine.

Your existing riskScore does not move — exploitPriority is a new axis beside it. And this is enrichment, not detection: it reorders what the scanner already found.

KNOWN_EXPLOITED
Listed by CISA as exploited in the wild
ELEVATED
EPSS ≥ 0.10 · roughly the top decile
BASELINE
Not elevated — asserts nothing more
Finding: MEDIUM, CVE on the KEV list
→ KEV flag + as-of date attached
→ band KNOWN_EXPLOITED
→ TOP OF QUEUE
Finding: CRITICAL, not on KEV, low EPSS
→ EPSS score + percentile attached
→ band BASELINE
→ RANKED BELOW IT
Store older than its window
→ KEV 14 days · EPSS 10 days
→ fails closed, withdraws the negative
→ NEVER SAYS “NOT EXPLOITED”

See Pro end to end — recorded on the 0.42 line:

The Pro overview covers exploit-first triage with CISA KEV and FIRST EPSS — free public feeds you download and point Pro at, failing closed when stale — offline-first CVE matching from detected service versions, findings emitted unverified for you to adjudicate, AI analysis on your own API keys, and risk-ranked reports built for one-click print to PDF.

Recorded on the NSAuditor AI 0.42 line · August 2026 · recorded before the report subcommand · exploit-first triage: CISA KEV + FIRST EPSS joined at scan time, feeds you download, stale feeds fail closed · findings emitted unverified — you adjudicate · AI on your own API keys · 6 min 13 s
Switch it on — two public feeds, two environment variables
# 1 · Download the feeds (public, no account needed for either)
mkdir -p ~/.nsauditor/feeds
curl -fsSL https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json -o ~/.nsauditor/feeds/kev.json
curl -fsSL https://epss.empiricalsecurity.com/epss_scores-current.csv.gz | gunzip > ~/.nsauditor/feeds/epss.csv

# 2 · Point the scanner at them (add both lines to your shell profile to persist)
export NSAUDITOR_EXPLOIT_KEV_STORE=~/.nsauditor/feeds/kev.json
export NSAUDITOR_EXPLOIT_EPSS_STORE=~/.nsauditor/feeds/epss.csv

# 3 · Scan as usual — findings that carry CVEs arrive banded and ordered exploit-first
nsauditor-ai scan --host 192.168.1.0/24 --plugins all

The stores are the feeds' own formats — no conversion step. Refresh KEV within 14 days and EPSS within 10 (a cron works); a stale or unparseable store fails closed and the scan says so — it never silently reports “not exploited”. Setting these outside a shell? ~ expands only in a shell — in a --env file or Claude Desktop’s MCP env config, write the absolute path (e.g. /Users/you/.nsauditor/feeds/kev.json); a path the scanner cannot read is reported as no-store, never as “not exploited”. Full walk-through: getting-started → exploit intelligence.

Exploit intelligence is a Pro-tier capability and is off until you configure it. Enterprise includes Pro.

Where Pro ends and the evidence pack begins

Pro sharpens the queue. Enterprise turns the result into something an assessor reads — 29 Enterprise plugins, 28 of them cloud auditors across AWS, Azure and GCP, and one read-only scan mapped to eight frameworks with an explicit out-of-scope column.

It is also where suppression lives — and suppression is an Enterprise capability, not a Pro one. Enterprise adds a suppression workflow for the compliance report: accepted-risk and false-positive records keyed on source and title pattern, approved with an approver’s signature, renewable on a cadence, and read by the compliance engine — which Pro does not run, so a suppression has no effect on a Pro report. The Enterprise compliance engine gives each decision an owner, a rationale, a date and an expiry inside the evidence pack — and as of EE 0.36.0 the report checks that approval’s signature against the key material the approver’s registry entry declares, rather than repeating what the record says about itself. A missing verdict reads not checked and never failed.

Isolated networks are Enterprise too: the offline install walkthrough — carry the package and the CVE data in, verify checksums, then import the feed — now lives on the Enterprise page.

None of that is part of a Pro licence. If your buyer is an auditor rather than a remediation queue, that is the tier to look at.

See NSAuditor AI Enterprise →

🎯

Exploit Intelligence

CISA KEV + FIRST EPSS joined by CVE ID at scan time, banded KNOWN_EXPLOITED / ELEVATED / BASELINE, queue ordered exploit-first. Operator-supplied catalogs; the join runs locally. See how →

🔎

Offline-First CVE Matching

Auto-generated CPEs from detected services matched against the NVD feed — offline-first: your local NVD store answers first, and on a miss the public NVD API is queried unless NSAUDITOR_OFFLINE_ONLY=1, which turns the miss into a coverage-gap finding instead of a request. Know which CVEs affect each host before writing a single line of your report.

🗺️

MITRE ATT&CK Annotations

Every finding is annotated with the ATT&CK techniques it relates to, with kill-chain context. Compliance teams love it. Clients understand it. Takes zero extra effort on your part.

🤖

Parallel Analysis Agents

Four analysis agents run concurrently on Pro — Auth, Crypto, Config and Service. The Exposure agent is Enterprise. Each produces structured findings for its category, then feeds the risk engine.

📊

Risk Scoring

CVSS weighted down while a finding is unverified — with a 15% uplift for findings carrying an initial-access ATT&CK technique. Reports render severity-grouped, highest-impact first.

📄

The Report You Send

report --from <run> --format executive renders a finished scan into one self-contained, print-ready HTML file that opens with no external network reference — optional cover-page branding via --brand. --format jira writes a Jira-importer CSV. Every scan still writes HTML, JSON and Markdown as before. See how →

🧠

Intelligence-Enriched AI

Same OpenAI / Claude / Ollama providers you use in CE — but Pro injects CVE matches, MITRE techniques, and risk scores into every prompt. Vastly better output.

🔁

Advanced CTEM

Unlimited scan history in SQLite. CVE-level delta detection — new vulnerabilities since last scan, not just host diffs. Risk trend analysis (improving / degrading / stable).

🔏

Enhanced Redaction

Configurable profiles (strict / moderate / minimal), additional patterns for AWS keys, DB connection strings, and JWTs. Full redaction audit log for compliance.

🔌

What Pro unlocks in the MCP tools

The MCP server registers seven tools and lists all seven to every client; the licence gate is applied when a tool is called. Pro unlocks probe_service and get_vulnerabilities on top of the three every tier can run.

🔑
Auth
Weak auth, default credentials, anonymous access, missing auth on admin panels
🔐
Crypto
TLS < 1.2, weak ciphers, expired or self-signed certs, missing HSTS
⚙️
Config
Default SNMP communities, debug modes, directory listing, exposed .env files
🛠️
Service
CVE-specific vulnerabilities, end-of-life software, backport detection
🌐
Exposure Enterprise
Internet-facing services, lateral movement paths, unnecessary open ports
Feature
Pro
Community
AI analysis (OpenAI, Claude, Ollama)
Prompt content
CVEs + MITRE + risk scores
basic summary
CVE matching (offline-first NVD)
MITRE ATT&CK annotations
Kill-chain context
basic tagging
Finding suppression (accepted-risk / false-positive)
Enterprise
Risk scoring
Exploit intelligence — CISA KEV + FIRST EPSS, exploit-first ordering (stores you populate; no feed data ships)
KEV-listed MEDIUM outranks unexploited CRITICAL
Parallel analysis agents
4 agents
Print-ready HTML reports (browser Print-to-PDF)
Risk-ranked, CVE-annotated
Ungated — same Print-to-PDF
Send-ready report subcommand — report --from <run> → executive HTML or Jira-importer CSV
Self-contained, no external references; container census on the page
CTEM scan history
Unlimited (JSONL)
7 days
MCP tools
5 of 7 usable
3 of 7
Email support
48hr SLA
probe_service Pro
Run one specific plugin against a single host:port. The narrow, surgical counterpart to a full scan — ask your assistant to check one service without re-scanning the host.
get_vulnerabilities Pro
Look up known CVEs for a CPE (Common Platform Enumeration) string via the NVD API — so your assistant can go from a detected version string to its published vulnerabilities.
scan_host
A full plugin scan of a target host: service detection, OS fingerprint and structured findings. Available on every tier.
compliance_matrix
The shipped coverage matrix for a framework — how many controls are Covered, Partial and Out of scope, with the per-group out-of-scope reasons. Available on every tier.

list_plugins completes the every-tier set; scan_cloud and get_findings are Enterprise. Seven tools in total — all seven are listed to every client, and the licence is checked when one is called.

Start the MCP server with nsauditor-ai-mcp — works with Claude Desktop, Cursor, and any MCP-compatible AI assistant.

1 · Authenticate with npm (token included in your purchase email)
# @nsasoft/nsauditor-ai-ee is a private (restricted) package.
# Use the npm read-token delivered with your license email.
npm config set //registry.npmjs.org/:_authToken npm_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# Or, project-scoped, in an .npmrc file
echo "//registry.npmjs.org/:_authToken=npm_xxxx..." >> ~/.npmrc
2 · Install (requires nsauditor-ai v0.2.49+ and Node 20+)
# One line — installs both the CE platform and the Pro package
npm install -g nsauditor-ai @nsasoft/nsauditor-ai-ee
3 · Activate your license — one command, no shell-rc edits
# The CE license installer verifies the JWT signature before persisting
# and stores the key in macOS Keychain (or ~/.nsauditor/.env mode 0600 elsewhere).
nsauditor-ai license install pro_eyJhbGciOiJFUzI1NiIs...

 Pro license installed
  Stored at: macOS Keychain (service=nsauditor-ai)
  Org: you@example.com   Expires: 2027-04-29

# Verify
nsauditor-ai license --status
 Pro license active
4 · Scan with intelligence
nsauditor-ai scan --host 192.168.1.0/24 --plugins all

# View your AI report in browser
open out/192.168.1.0_*/scan_response_ai.html     # macOS
xdg-open out/192.168.1.0_*/scan_response_ai.html  # Linux

# Each scan writes HTML, JSON, and Markdown reports — print the HTML to PDF for clients
nsauditor-ai scan --host 10.0.0.0/24 --plugins all
open out/10.0.0.0_*/scan_response_ai.html      # print → PDF

# And turn that finished run into the one file you send the client
nsauditor-ai report --from out/10.0.0.0_<timestamp> --format executive

Ready to upgrade?

Subscribe directly to unlock CVE matching, MITRE ATT&CK annotations, risk scoring, and parallel analysis agents — and the report subcommand that turns a finished scan into one self-contained HTML file you can send, or a Jira-importer CSV. Cancel anytime; an annual plan stays active to the end of its paid year, then reverts to Community Edition with no data lost.

Monthly option: $49/mo · Compare all plans