nsauditor-ai 0.1.36 → 0.1.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -241
- package/bin/nsauditor-ai-mcp.mjs +9 -5
- package/mcp_server.mjs +27 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,204 +7,22 @@ A modular, AI-assisted network security audit platform that scans, understands,
|
|
|
7
7
|
[](https://www.npmjs.com/package/nsauditor-ai)
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
[](https://nodejs.org)
|
|
10
|
-
[](#tests)
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
NSAuditor AI is the open-source core of a privacy-first security intelligence platform built by [Nsasoft US LLC](https://www.nsauditor.com/ai/). It orchestrates
|
|
14
|
+
NSAuditor AI is the open-source core of a privacy-first security intelligence platform built by [Nsasoft US LLC](https://www.nsauditor.com/ai/). It orchestrates 27 specialized scanning plugins against target hosts, fuses their results through an intelligent concluder, and optionally produces AI-powered vulnerability reports — all running entirely on your machine.
|
|
15
15
|
|
|
16
16
|
**Zero Data Exfiltration by design.** NSAuditor AI works fully offline. AI analysis, CVE correlation, and continuous monitoring all happen locally. External calls (to AI APIs, NVD, etc.) are opt-in and use your own API keys. We never see your scan data.
|
|
17
17
|
|
|
18
|
-
## What's New
|
|
18
|
+
## What's New
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
**
|
|
23
|
-
- Each `tools/call` invocation mints a fresh server-side UUID via Node's `crypto.randomUUID()`.
|
|
24
|
-
- The UUID is appended to the response text under a `── Verified MCP call ──` footer.
|
|
25
|
-
- The same UUID is persisted to `~/.nsauditor/mcp-calls.log` (mode 0600, JSON-per-line) **before** the response is returned.
|
|
26
|
-
- A new CLI subcommand `nsauditor-ai mcp verify-call <uuid>` greps the log:
|
|
27
|
-
- **Found** → the UUID was issued by your local MCP server, so the response bearing it is genuine.
|
|
28
|
-
- **Not found** → the UUID was never issued, so the entire response was fabricated by the AI client.
|
|
29
|
-
|
|
30
|
-
**Customer verification workflow (10 seconds):**
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
# 1. In Claude Desktop, ask Claude to use any MCP tool (e.g., list_plugins).
|
|
34
|
-
# 2. The response ends with:
|
|
35
|
-
# ── Verified MCP call ──
|
|
36
|
-
# call_id: 3f8a1b22-7e44-4c91-9d62-12bd0a4f5e91
|
|
37
|
-
# Verify: nsauditor-ai mcp verify-call 3f8a1b22-7e44-4c91-9d62-12bd0a4f5e91
|
|
38
|
-
# 3. Run that exact verify command in your terminal:
|
|
39
|
-
nsauditor-ai mcp verify-call 3f8a1b22-7e44-4c91-9d62-12bd0a4f5e91
|
|
40
|
-
# ✓ Verified MCP call → genuine
|
|
41
|
-
# ✗ call_id not found → fabricated (response was AI-generated, not from the MCP server)
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
This makes the hallucination detection unfakeable in principle: the AI client has no access to your local Node `crypto.randomUUID()` output, and the sentinel is generated **at the moment the call hits the server** — there's no way to forge a UUID that will appear in a log file the client cannot read or write.
|
|
45
|
-
|
|
46
|
-
The 0.1.34/0.1.35 version-block check remains as the first line of defense (instant visual mismatch). The 0.1.36 UUID is the cryptographic ground truth for any response you'd act on.
|
|
47
|
-
|
|
48
|
-
`scan_host`, `probe_service`, `get_vulnerabilities`, and `list_plugins` all mint sentinels — even Pro-tier denials carry a UUID so customers can prove the call reached the server.
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
npm install -g nsauditor-ai@0.1.36
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
## What's New (0.1.35) — CLI provenance footer matches MCP response (so the comparison actually works)
|
|
57
|
-
|
|
58
|
-
0.1.34 added the version-provenance block to the MCP server's `list_plugins` response, but **the CLI baseline (`license --plugins` / `license --status`) didn't show versions** — so customers couldn't easily compare. 0.1.35 fixes that asymmetry.
|
|
59
|
-
|
|
60
|
-
Both CLI commands now emit an identical provenance block:
|
|
61
|
-
|
|
62
|
-
```
|
|
63
|
-
── Installation provenance ──
|
|
64
|
-
nsauditor-ai (CE): 0.1.35
|
|
65
|
-
@nsasoft/nsauditor-ai-ee (EE): 0.3.4 (loaded)
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
**Customer hallucination-detection workflow (5 seconds, no log archeology):**
|
|
69
|
-
|
|
70
|
-
1. In Claude Desktop: ask "list plugins" → receive a response that should end with the provenance block
|
|
71
|
-
2. In your terminal: run `nsauditor-ai license --plugins`
|
|
72
|
-
3. Compare the two `── Installation provenance ──` blocks character-for-character
|
|
73
|
-
4. **Match** → real MCP `tools/call` happened, response is trustworthy
|
|
74
|
-
5. **Mismatch / missing block** → Claude fabricated the response (see CE 0.1.33 advisory)
|
|
75
|
-
|
|
76
|
-
This is the v1 mitigation; the v2 (Thread L Phase 2) adds per-call cryptographic sentinel UUIDs that the customer can grep against the server log directly. v1 catches the common case where Claude either omits the block entirely (unlikely to fabricate the new structure verbatim) or includes a stale version pulled from training data.
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
## What's New (0.1.34) — list_plugins now embeds CE+EE versions for hallucination detection
|
|
81
|
-
|
|
82
|
-
Companion to the 0.1.33 advisory. The `list_plugins` MCP tool's response now appends the actual installed CE + EE version numbers, so customers can verify a Claude Desktop response in **5 seconds** without log archeology:
|
|
83
|
-
|
|
84
|
-
```
|
|
85
|
-
── Installation provenance (verify against your shell) ──
|
|
86
|
-
nsauditor-ai (CE): 0.1.34
|
|
87
|
-
@nsasoft/nsauditor-ai-ee (EE): 0.3.4 (loaded)
|
|
88
|
-
Verify: nsauditor-ai --version && npm list -g @nsasoft/nsauditor-ai-ee
|
|
89
|
-
If versions in this response don't match your shell, the response was
|
|
90
|
-
AI-generated rather than retrieved from the MCP server (see CE 0.1.33 advisory).
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
How it works as a hallucination detector:
|
|
94
|
-
- The MCP server reads `process.execPath`'s package.json + tries to resolve `@nsasoft/nsauditor-ai-ee/package.json` at request time. Both are real machine-specific values.
|
|
95
|
-
- Claude Desktop fabricated responses in the wild have shown stale version numbers from training data, missing version lines entirely, or different counts each time the same question is asked (observed 32→32→31 plugin counts in three consecutive hallucinations on 2026-05-10).
|
|
96
|
-
- A real tool response will exactly match `nsauditor-ai --version` + `npm list -g @nsasoft/nsauditor-ai-ee`. Mismatch = hallucinated.
|
|
97
|
-
|
|
98
|
-
This is a v1 mitigation — the v2 (Thread L in `tasks/todo.md`) adds per-call cryptographic sentinel UUIDs that the customer can grep against the server log.
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
## What's New (0.1.33) — ⚠ MCP integration with Claude Desktop is unreliable
|
|
103
|
-
|
|
104
|
-
**Critical advisory for customers using NSAuditor AI through Claude Desktop's MCP integration.** During the maintainer's own integration test on 2026-05-10, we discovered that **Claude Desktop's AI fabricates scan results, plugin lists, vulnerability findings, and tier information without actually invoking the MCP tools** for our specific server. Other MCP servers in the same Claude Desktop config receive real `tools/call` invocations; ours does not.
|
|
105
|
-
|
|
106
|
-
**Empirical evidence**:
|
|
107
|
-
- `~/Library/Logs/Claude/main.log` shows multiple permission grants for `mcp__nsauditor-ai__list_plugins` and `mcp__nsauditor-ai__scan_host` on 2026-05-10
|
|
108
|
-
- `~/Library/Logs/Claude/mcp-server-nsauditor-ai.log` shows **zero** `"method":"tools/call"` entries on the same day
|
|
109
|
-
- Other servers in the same config logged real calls (ns-ftp:29, wp-publisher-netsecmag:14, ai-pr-distribution:6, sendgrid:3)
|
|
110
|
-
- When asked to scan 1.1.1.1, Claude Desktop returned a detailed report with plugin breakdown + Zero Trust score — entirely fabricated
|
|
111
|
-
|
|
112
|
-
**Likely cause**: Claude Desktop's MCP client appears to time out our server (which loads PluginManager + 32 plugins + license verify before responding). Claude (the AI) silently substitutes fabricated responses from training rather than surfacing the timeout. The hallucinations are convincingly formatted and indistinguishable from real output without log inspection.
|
|
113
|
-
|
|
114
|
-
**Mandatory verification — for any output you'd act on**:
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
# Tier check (ground truth bypassing Claude AI synthesis):
|
|
118
|
-
nsauditor-ai mcp tier
|
|
119
|
-
|
|
120
|
-
# Real plugin scan (always hits the network):
|
|
121
|
-
nsauditor-ai scan --host <X> --plugins all --out <dir>
|
|
122
|
-
|
|
123
|
-
# Confirm Claude Desktop actually called the MCP server:
|
|
124
|
-
grep '"method":"tools/call"' ~/Library/Logs/Claude/mcp-server-nsauditor-ai.log | tail -5
|
|
125
|
-
# If main.log shows recent permission grants for nsauditor-ai tools but
|
|
126
|
-
# THIS file shows no matching tools/call entries, the responses you saw
|
|
127
|
-
# in Claude Desktop were AI-generated, NOT real.
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
**SOC 2 evidence and any compliance report MUST be generated via the CLI** — never via the Claude Desktop MCP integration — until this is resolved upstream. We're working on it (Thread L in `tasks/todo.md`): a per-call cryptographic sentinel, lazy-loaded plugin discovery to reduce startup latency, a `mcp verify-recent-call` diagnostic, and a bug report to Anthropic.
|
|
131
|
-
|
|
132
|
-
This advisory will be removed when the upstream Claude Desktop MCP routing issue is fixed and we ship a CE release whose `tools/call` invocations land reliably.
|
|
133
|
-
|
|
134
|
-
---
|
|
135
|
-
|
|
136
|
-
## What's New (0.1.32) — Claude Desktop integration overhaul + ground-truth diagnostics
|
|
137
|
-
|
|
138
|
-
The 0.1.32 line bundles three operational improvements driven by real customer-onboarding friction surfaced during the developer's own Claude Desktop integration test (2026-05-10):
|
|
139
|
-
|
|
140
|
-
- **`nsauditor-ai mcp install-key` now auto-generates a machine-specific Claude Desktop config snippet.** Reads `process.execPath` (the Node binary actually running) and derives the script path from `import.meta.url` — the printed JSON has absolute paths that work whether you're on system Node, homebrew, nvm, fnm, local-project install, Linux, or Windows. No install-type detective work, no PATH-misalignment failures. On macOS, the snippet uses `keychain:` indirection for **both** auth and license — secrets never land in the world-readable Claude Desktop config file.
|
|
141
|
-
- **License `keychain:` indirection.** `loadLicense()` and `resolveLicenseKey()` honor the `keychain:LABEL` prefix on the env-supplied value (mirrors the EE-SEC.1 MCP-auth pattern). Operators can put `"NSAUDITOR_LICENSE_KEY": "keychain:NSAUDITOR_LICENSE_KEY"` in their Claude Desktop env block; the JWT stays in macOS Keychain. Backward-compat: literal JWTs continue to work unchanged.
|
|
142
|
-
- **`nsauditor-ai mcp tier` ground-truth subcommand.** Customer-side check that prints the EXACT tier the spawned MCP server resolves to. We discovered Claude Desktop reports of "Current tier: CE" despite verified Pro/Enterprise license were caused by Claude (the AI) **synthesizing the tier text from training data + context** instead of actually calling `list_plugins` via MCP. The MCP server's resolution was always correct. `mcp tier` bypasses Claude's interpretive layer — paste the output into a support ticket to distinguish "MCP genuinely broken" from "Claude misreading."
|
|
143
|
-
- **MCP key rotation cadence (Thread I).** Optional 90-day rotation soft warning at server startup + `mcp status` (override via `NSA_MCP_AUTH_KEY_ROTATION_DAYS`, clamped to [7, 365]). SOC 2 CC6.1/CC6.7 reviewers expect a credential-rotation cadence; an unrotated MCP auth key is treated the same way as an unrotated IAM access key.
|
|
144
|
-
- **Keychain-locked vs Keychain-empty distinction.** New `keychain-locked` source variant in `mcp status` for headless macOS / SSH-only CI runners — instead of falling through silently to "unconfigured", operators get an actionable error with three GUI-free workarounds.
|
|
145
|
-
- **Atomic file writes** for `~/.nsauditor/.env` (`.tmp` + POSIX-rename) so concurrent readers + crash recovery never observe a truncated file.
|
|
146
|
-
- **Auto-mirror license file→Keychain on `mcp install-key`** (macOS) when the license is configured in `~/.nsauditor/.env` but absent from Keychain. Lets the printed snippet's `keychain:` indirection actually resolve, with original storage location preserved unchanged.
|
|
147
|
-
|
|
148
|
-
**Breaking change for existing 0.1.31 operators**: nothing breaks, but the recommended Claude Desktop config snippet has changed. Re-run `nsauditor-ai mcp install-key` after upgrading to get the new auto-generated snippet with absolute paths + license indirection. Old configs continue to work.
|
|
149
|
-
|
|
150
|
-
```bash
|
|
151
|
-
npm install -g nsauditor-ai@0.1.32
|
|
152
|
-
nsauditor-ai mcp install-key # prints the new snippet — paste into Claude Desktop config
|
|
153
|
-
nsauditor-ai mcp tier # confirm the actual MCP server tier (ground truth)
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
See [Authentication](#authentication-required-new-in-0131) and [Troubleshooting MCP authentication](#troubleshooting-mcp-authentication) for full setup + diagnostics.
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
## What's New (0.1.31) — security release
|
|
161
|
-
|
|
162
|
-
**MCP server authentication is now required.** Pre-0.1.31, the local MCP server (stdio transport) accepted any incoming JSON-RPC frames — any process running as your user could spawn it and use the Pro/Enterprise tools (which include the AWS-talking shadow-admin path detectors that ship in `@nsasoft/nsauditor-ai-ee@0.3.4`). 0.1.31 closes this gap with a per-operator shared-secret check at startup.
|
|
163
|
-
|
|
164
|
-
**Breaking change for existing operators**: after upgrading, run `nsauditor-ai mcp install-key` once. Without this step, the MCP server refuses to start and Claude Desktop will report a connection failure. The error message points back at this command.
|
|
165
|
-
|
|
166
|
-
```bash
|
|
167
|
-
npm install -g nsauditor-ai@0.1.31
|
|
168
|
-
nsauditor-ai mcp install-key # generates a 256-bit key, persists it, prints Claude Desktop config snippet
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
**What's in the box (EE-SEC.1):**
|
|
172
|
-
|
|
173
|
-
- `nsauditor-ai mcp install-key` — generates a 256-bit auth key, stores it in macOS Keychain (or `~/.nsauditor/.env` mode 0600 elsewhere), prints a paste-ready Claude Desktop config snippet. Run once per machine.
|
|
174
|
-
- `nsauditor-ai mcp status` / `print-key --confirm` / `rotate-key --confirm` — inspect, reveal (TTY-only by default), and rotate the key.
|
|
175
|
-
- **`keychain:` indirection on macOS** — the printed config snippet uses `"NSA_MCP_AUTH_KEY": "keychain:NSA_MCP_AUTH_KEY"` instead of the literal key. The MCP server resolves the placeholder at startup; **the secret never lands in your `claude_desktop_config.json`** (which is mode 0644 on macOS by default — readable by other local users and any sandboxed app). On Linux/Windows where there's no Keychain equivalent, the snippet falls back to the literal key with a `chmod 600` warning.
|
|
176
|
-
- **`NSA_MCP_AUTH_DISABLE=1`** escape hatch for CI / dev — emits a stderr warning every startup so you don't forget; a louder warning fires when DISABLE is set AND no key was ever installed.
|
|
177
|
-
- Multi-source resolver mirrors the existing license-key pattern: env → Keychain → file. Constant-time key comparison via `crypto.timingSafeEqual`. Two-reviewer cycle (general code review + network-security-audit lens) caught and folded 2 CRITICAL + 5 MEDIUM findings same-session before commit; full threat model documented in [`utils/mcp_auth.mjs`](./utils/mcp_auth.mjs).
|
|
178
|
-
|
|
179
|
-
See the [MCP Server § Authentication section](#authentication-required-new-in-0131) for the full setup walkthrough, troubleshooting, and the threat-model table.
|
|
20
|
+
- **0.1.38 (current)** — docs-only. README rewritten to be feature-and-usage focused; release history moved to [CHANGELOG.md](./CHANGELOG.md); new [docs/mcp-verification.md](./docs/mcp-verification.md) for the `nsauditor-ai mcp verify-call` workflow. No functional change vs 0.1.37.
|
|
21
|
+
- **0.1.37 — 🛑 security fix**, upgrade if you're on anything earlier. The MCP bin shim (`nsauditor-ai-mcp`) was bypassing both `NSA_MCP_AUTH_KEY` enforcement and license verification on every spawn. Defense-in-depth degradation, plus paid Pro/Enterprise customers were stuck at CE tier through MCP. `npm install -g nsauditor-ai@latest` + restart your MCP client.
|
|
22
|
+
- **Authenticated MCP server, Keychain-backed secrets, per-call sentinel UUIDs, multi-source license loader, `--version` / `validate` / `license install` subcommands.** All shipped across 0.1.30 → 0.1.37 — see [CHANGELOG.md](./CHANGELOG.md) for the per-release detail.
|
|
180
23
|
|
|
181
24
|
---
|
|
182
25
|
|
|
183
|
-
## What's New in Enterprise Edition (0.3.3)
|
|
184
|
-
|
|
185
|
-
The Enterprise Edition (`@nsasoft/nsauditor-ai-ee`) shipped a 0.3.3 point release on 2026-05-08. CE stays at 0.1.30 — no bump required, the EE upgrade is single-line: `npm install -g @nsasoft/nsauditor-ai-ee@latest`. The release closes a Critical false-clean SOC 2 reporting bug that mirrored the AWS-side bug fixed in 0.3.2 — this time in the Azure cloud scanner — and extends mapped SOC 2 coverage to multi-cloud:
|
|
186
|
-
|
|
187
|
-
- **Azure plugin (022) finding-shape rewrite** — the EE-0.3.2.1 cloud-finding harvester only recognized one canonical shape (`{resource, severity, issues[]}`); plugin 022 was emitting `{severity, finding, resource}` (singular `finding`). Findings reached the engine but were silently dropped — Azure customers running `--compliance soc2` saw "6/6 covered controls passing" against subscriptions with real RBAC + NSG + Storage issues. Caught at internal dogfood against a live Azure subscription.
|
|
188
|
-
- **GCP plugin (021) preventive shape port** — plugin 021 had the same `{finding}` singular shape; pre-emptively migrated to the canonical shape so the same bug doesn't re-emerge for GCP customers in v0.4.0 when GCP `mapsToFindings` rules ship.
|
|
189
|
-
- **Azure → SOC 2 mapping rules added** — RBAC `Owner | Contributor | User Access Administrator at subscription scope` → CC6.1 (3 patterns); NSG `0.0.0.0/0 → port` anchored regex → CC6.6; Storage `allowBlobPublicAccess` + `enableHttpsTrafficOnly` → C1.1. CC6.1, CC6.6, and C1.1 now have *both* AWS-side and Azure-side evidence rows — actual multi-cloud SOC 2 evidence.
|
|
190
|
-
- **Drift detector extended to all three cloud plugins** — every `azure-cloud-scanner` `titlePattern` in `soc2.json` is now asserted to match at least one canonical issue string the plugin emits, and vice versa. The class-of-bug that produced two false-clean variants in successive releases is now structurally closed.
|
|
191
|
-
- **Pre-publish gate fixes** — `@azure/arm-authorization` peer-dep was pinned at `^10.0.0` (latest published is 9.0.0; clean installs would have failed); `@azure/arm-storage` was missing from `optionalDependencies` (Storage audit silently no-op'd on clean install). Both caught at the pre-publish clean-tarball smoke and corrected before ship.
|
|
192
|
-
|
|
193
|
-
See [EE README](https://www.npmjs.com/package/@nsasoft/nsauditor-ai-ee) for the full 0.3.3 changelog and Azure scan walkthrough.
|
|
194
|
-
|
|
195
|
-
---
|
|
196
|
-
|
|
197
|
-
## What's New (0.1.30)
|
|
198
|
-
|
|
199
|
-
The 0.1.30 line is a paired release with `@nsasoft/nsauditor-ai-ee@0.3.2` that closes the customer-onboarding gap and a critical false-clean SOC 2 reporting bug:
|
|
200
|
-
|
|
201
|
-
- **`nsauditor-ai license install <KEY>`** — verifies the JWT *before* persisting; writes to macOS Keychain or `~/.nsauditor/.env` (mode 0600) depending on platform. Three-line install flow: `npm install -g` → `license install` → `license --status`. No more shell-rc edits.
|
|
202
|
-
- **Multi-source license loader** — `loadLicense()` resolves keys from env var → platform Keychain → `~/.nsauditor/.env`, in that order. CI/CD env-var override still wins.
|
|
203
|
-
- **`nsauditor-ai license --plugins`** — real enumeration of discovered plugins, grouped by source (CE / EE / custom), with active-or-required-tier status.
|
|
204
|
-
- **`nsauditor-ai --version` / `-v`** — prints version and exits 0 (parallel to `--help`'s discovery-flag UX).
|
|
205
|
-
- **Cloud-sentinel SSRF bypass** — `--host aws|gcp|azure` no longer requires `NSA_ALLOW_ALL_HOSTS=1`. The sentinel literals route to EE cloud-scanner plugins via the provider's API; the SSRF guard's RFC 1918 / loopback protection is preserved for real network targets.
|
|
206
|
-
- **EE-0.3.2.1 hard dep** — CE forwards the per-plugin `results` array to `enrichScan()`. Without this, EE 0.3.2's cloud-finding harvester sees nothing and produces false-clean SOC 2 reports against AWS accounts. EE emits a runtime version-skew warning when this opt is missing.
|
|
207
|
-
|
|
208
26
|
## What It Does
|
|
209
27
|
|
|
210
28
|
```
|
|
@@ -359,10 +177,11 @@ Results land in `./out/<host>_<timestamp>/`:
|
|
|
359
177
|
|
|
360
178
|
| ID | Name | Tier | Purpose |
|
|
361
179
|
|---|---|---|---|
|
|
362
|
-
| 020 | AWS Cloud Scanner | Enterprise |
|
|
180
|
+
| 020 | AWS Cloud Scanner | Enterprise | S3 bucket hardening, security group + IAM policy analysis with SOC 2 evidence mapping |
|
|
363
181
|
| 021 | GCP Cloud Scanner | Enterprise | Firewall rules + IAM bindings |
|
|
364
|
-
| 022 | Azure Cloud Scanner | Enterprise | NSG rules + RBAC role assignments + Storage account hardening
|
|
182
|
+
| 022 | Azure Cloud Scanner | Enterprise | NSG rules + RBAC role assignments + Storage account hardening, SOC 2 evidence mapping (CC6.1 / CC6.6 / C1.1) |
|
|
365
183
|
| 023 | Zero Trust Checker | Enterprise | Segmentation, encryption, identity, lateral movement scoring |
|
|
184
|
+
| 030 | AWS IAM Deep Auditor | Enterprise | Shadow-admin path detection via BFS over PassRole / AssumeRole / federated trust; per-finding remediation pointers; SOC 2 CC6.1 evidence |
|
|
366
185
|
| — | SOC 2 Compliance Engine | Enterprise | AICPA TSC 2017 control mapping, chain-of-custody, RFC 3161 timestamps, suppression workflow |
|
|
367
186
|
| — | SLA & MTTR Tracking | Enterprise | Per-severity SLA targets, compensating-control flow, finding lifecycle |
|
|
368
187
|
| — | Recurring-Scan Attestation | Enterprise | Multi-scan chronological matrix, cadence gap detection, scope drift (CC8.1) |
|
|
@@ -437,27 +256,7 @@ nsauditor-ai scan --host 192.168.1.0/24 --plugins all \
|
|
|
437
256
|
|
|
438
257
|
## MCP Server
|
|
439
258
|
|
|
440
|
-
>
|
|
441
|
-
>
|
|
442
|
-
> When you use NSAuditor AI through **Claude Desktop's** MCP integration, the AI may **fabricate scan results, plugin lists, vulnerability findings, and tier information without actually invoking the MCP tools**. We've confirmed this empirically: Claude Desktop's permission system shows tool calls being approved, but the actual `tools/call` JSON-RPC messages never reach our server (other MCP servers in the same config receive their calls correctly).
|
|
443
|
-
>
|
|
444
|
-
> **Mandatory verification for any output you'd act on (NEW in 0.1.36 — works for any MCP client):**
|
|
445
|
-
>
|
|
446
|
-
> ```bash
|
|
447
|
-
> # Cryptographic ground truth: copy the call_id from the response footer
|
|
448
|
-
> # ("── Verified MCP call ──") and run:
|
|
449
|
-
> nsauditor-ai mcp verify-call <call_id>
|
|
450
|
-
> # ✓ Verified MCP call → genuine, response is trustworthy
|
|
451
|
-
> # ✗ call_id not found → fabricated, IGNORE the response
|
|
452
|
-
>
|
|
453
|
-
> # Real tier check (bypasses Claude AI synthesis):
|
|
454
|
-
> nsauditor-ai mcp tier
|
|
455
|
-
>
|
|
456
|
-
> # Real scan (always hits the network, no MCP client involved):
|
|
457
|
-
> nsauditor-ai scan --host <X> --plugins all --out <dir>
|
|
458
|
-
> ```
|
|
459
|
-
>
|
|
460
|
-
> **SOC 2 evidence + compliance reports MUST be generated via the CLI** — never via the Claude Desktop MCP integration — unless every response you act on has a verified call_id. Other MCP clients (Claude Code, custom MCP clients via the SDK) appear unaffected. See [What's New (0.1.36)](#whats-new-0136--cryptographic-per-call-sentinel-uuid-hallucination-becomes-mathematically-detectable) for the cryptographic mitigation and [What's New (0.1.33)](#whats-new-0133----mcp-integration-with-claude-desktop-is-unreliable) for the original advisory.
|
|
259
|
+
> **Heads-up on AI-client fabrication.** Some MCP clients (notably Claude Desktop) can silently substitute AI-generated responses if a `tools/call` times out, instead of surfacing the failure. Every response from this server now ends with a `── Verified MCP call ──` footer and a UUID. Run `nsauditor-ai mcp verify-call <id>` to confirm a response is genuine before acting on it. Full background and workflow: [docs/mcp-verification.md](./docs/mcp-verification.md). When in doubt, generate compliance evidence via the CLI (`nsauditor-ai scan ...`), which has no MCP client in the path.
|
|
461
260
|
|
|
462
261
|
Expose scanning capabilities to AI assistants via [Model Context Protocol](https://modelcontextprotocol.io):
|
|
463
262
|
|
|
@@ -493,11 +292,11 @@ npx nsauditor-ai-mcp
|
|
|
493
292
|
| `compliance_check` | Compliance mapping with gap analysis |
|
|
494
293
|
| `export_report` | Generate formatted compliance report |
|
|
495
294
|
|
|
496
|
-
Security: SSRF protection on all host inputs (blocks RFC 1918, loopback, fc00::/7, cloud metadata), port validation (1–65535), CPE format enforcement, dependency injection for test isolation. **Server-startup authentication required
|
|
295
|
+
Security: SSRF protection on all host inputs (blocks RFC 1918, loopback, fc00::/7, cloud metadata), port validation (1–65535), CPE format enforcement, dependency injection for test isolation. **Server-startup authentication is required** — see next section.
|
|
497
296
|
|
|
498
|
-
### Authentication (required
|
|
297
|
+
### Authentication (required)
|
|
499
298
|
|
|
500
|
-
The MCP server uses stdio transport, which means it runs as a child process of whatever client launches it. Without authentication, **any process running as your user could spawn the server and use its tools** — including the Pro/Enterprise tools that talk to AWS, generate compliance reports, and access your scan history.
|
|
299
|
+
The MCP server uses stdio transport, which means it runs as a child process of whatever client launches it. Without authentication, **any process running as your user could spawn the server and use its tools** — including the Pro/Enterprise tools that talk to AWS, generate compliance reports, and access your scan history. A per-operator shared-secret check at server startup closes this gap.
|
|
501
300
|
|
|
502
301
|
**One-time setup** (run once per machine after `npm install -g nsauditor-ai`):
|
|
503
302
|
|
|
@@ -536,7 +335,7 @@ nsauditor-ai mcp rotate-key --confirm # generates a new key (invalidates old
|
|
|
536
335
|
|
|
537
336
|
A shell-wrapper indirection script (read key from `~/.nsauditor/.env` at exec time, pass to child) was considered for v1 but does NOT solve the underlying issue: the spawned MCP server still needs the key in its env to perform the auth check, so it appears in `/proc/<server-pid>/environ` regardless of how the parent process obtained it. v2 may add libsecret integration on Linux to mirror the macOS Keychain indirection model.
|
|
538
337
|
|
|
539
|
-
**Rotation cadence
|
|
338
|
+
**Rotation cadence**: keys older than 90 days emit a soft warning at every server startup AND in `nsauditor-ai mcp status` output. SOC 2 CC6.1 / CC6.7 reviewers expect a credential-rotation cadence; rotate with `nsauditor-ai mcp rotate-key --confirm` and update Claude Desktop config with the new key.
|
|
540
339
|
|
|
541
340
|
**Escape hatch for CI / dev** (operator-acknowledged risk; emits a stderr warning every startup):
|
|
542
341
|
|
|
@@ -550,7 +349,7 @@ First install the package globally:
|
|
|
550
349
|
|
|
551
350
|
```bash
|
|
552
351
|
npm install -g nsauditor-ai
|
|
553
|
-
nsauditor-ai mcp install-key #
|
|
352
|
+
nsauditor-ai mcp install-key # required before MCP server will start
|
|
554
353
|
```
|
|
555
354
|
|
|
556
355
|
Then add this to your `claude_desktop_config.json` (Settings → Developer → Edit Config):
|
|
@@ -574,7 +373,7 @@ Then add this to your `claude_desktop_config.json` (Settings → Developer → E
|
|
|
574
373
|
|
|
575
374
|
The exact `NSA_MCP_AUTH_KEY` value to paste is printed by `nsauditor-ai mcp install-key` — on macOS it's the `keychain:NSA_MCP_AUTH_KEY` placeholder shown above; on Linux/Windows it's the literal key value (and you should `chmod 600` your config file).
|
|
576
375
|
|
|
577
|
-
- `NSA_MCP_AUTH_KEY` — **required
|
|
376
|
+
- `NSA_MCP_AUTH_KEY` — **required** (see Authentication section above)
|
|
578
377
|
- `NSA_ALLOW_ALL_HOSTS=1` — required to scan private/RFC 1918 addresses (e.g., `192.168.x.x`)
|
|
579
378
|
- `PLUGIN_TIMEOUT_MS=5000` — reduces per-plugin timeout to 5s so the full scan completes within Claude Desktop's 60s MCP limit
|
|
580
379
|
- `AI_PROVIDER` and API key — optional, enables AI-powered analysis of scan results
|
|
@@ -582,7 +381,7 @@ The exact `NSA_MCP_AUTH_KEY` value to paste is printed by `nsauditor-ai mcp inst
|
|
|
582
381
|
### Claude Code Setup
|
|
583
382
|
|
|
584
383
|
```bash
|
|
585
|
-
nsauditor-ai mcp install-key #
|
|
384
|
+
nsauditor-ai mcp install-key # required before MCP server will start
|
|
586
385
|
claude mcp add nsauditor-ai \
|
|
587
386
|
--env NSA_MCP_AUTH_KEY=keychain:NSA_MCP_AUTH_KEY \
|
|
588
387
|
-- npx nsauditor-ai-mcp
|
|
@@ -600,28 +399,11 @@ claude mcp add nsauditor-ai \
|
|
|
600
399
|
|
|
601
400
|
**"MCP_AUTH uses keychain: indirection but the referenced Keychain entry could not be read"** → typically a headless macOS / SSH-only CI runner where there's no GUI session to approve Keychain access. Replace the `keychain:` placeholder with the literal key value (or move auth to `~/.nsauditor/.env` with mode 0600).
|
|
602
401
|
|
|
603
|
-
**`mcp status` reports `keychain-locked`**
|
|
604
|
-
|
|
605
|
-
**`mcp status` shows `⚠ Created: ... — > 90d threshold`** (NEW in 0.1.32) → key is older than the 90-day rotation cadence. Run `nsauditor-ai mcp rotate-key --confirm` and update Claude Desktop config with the new key. Server emits the same warning to stderr at every startup.
|
|
606
|
-
|
|
607
|
-
**Claude Desktop reports "Current tier: CE" despite `nsauditor-ai license --status` showing Enterprise** (NEW in 0.1.32) → first run `nsauditor-ai mcp tier` to get the **ground-truth tier** the MCP server actually resolves at startup. If `mcp tier` reports `enterprise` but Claude Desktop's `list_plugins` says CE, **Claude (the AI) is synthesizing the tier text from context rather than calling the tool**. Force a real call by asking in a NEW Claude Desktop conversation:
|
|
608
|
-
|
|
609
|
-
> Use the `list_plugins` MCP tool right now and show me the raw tool response verbatim, including the exact text after the JSON.
|
|
610
|
-
|
|
611
|
-
Then verify a real call happened. The 0.1.36+ way (works for any client, not just Claude Desktop):
|
|
402
|
+
**`mcp status` reports `keychain-locked`** → distinct from `unconfigured`: the Keychain entry exists but the security daemon refused to unlock without a GUI prompt. Same workarounds as the previous error: approve a Keychain GUI prompt, replace `keychain:` indirection with the literal key, or move auth to `~/.nsauditor/.env`.
|
|
612
403
|
|
|
613
|
-
|
|
614
|
-
# Copy the call_id from the response footer that Claude returned, then:
|
|
615
|
-
nsauditor-ai mcp verify-call <call_id>
|
|
616
|
-
# ✓ Verified MCP call → genuine, response is trustworthy
|
|
617
|
-
# ✗ call_id not found → fabricated, IGNORE the response
|
|
618
|
-
```
|
|
619
|
-
|
|
620
|
-
The pre-0.1.36 fallback (Claude Desktop log archeology):
|
|
404
|
+
**`mcp status` shows `⚠ Created: ... — > 90d threshold`** → key is older than the 90-day rotation cadence. Run `nsauditor-ai mcp rotate-key --confirm` and update Claude Desktop config with the new key. Server emits the same warning to stderr at every startup.
|
|
621
405
|
|
|
622
|
-
|
|
623
|
-
grep '"method":"tools/call"' ~/Library/Logs/Claude/mcp-server-nsauditor-ai.log | tail -5
|
|
624
|
-
```
|
|
406
|
+
**Claude Desktop reports "Current tier: CE" despite `nsauditor-ai license --status` showing Enterprise** → first run `nsauditor-ai mcp tier` to get the ground-truth tier the MCP server actually resolves at startup. If `mcp tier` reports `enterprise` but Claude Desktop's `list_plugins` says CE, the AI client is synthesizing the response without actually calling the tool — see [docs/mcp-verification.md](./docs/mcp-verification.md) and verify any suspicious response with `nsauditor-ai mcp verify-call <id>`.
|
|
625
407
|
|
|
626
408
|
If `mcp tier` itself reports CE → genuine resolution failure. Inspect the license storage:
|
|
627
409
|
|
|
@@ -678,7 +460,7 @@ nsauditor-ai --help (or -h, or `help`)
|
|
|
678
460
|
nsauditor-ai --version (or -v, or `version`)
|
|
679
461
|
```
|
|
680
462
|
|
|
681
|
-
> Run `nsauditor-ai --help` (or `-h`, or just `nsauditor-ai help`) for a quick reference of subcommands, flags, env vars, and worked examples — works without a license key configured. `--version` / `-v`
|
|
463
|
+
> Run `nsauditor-ai --help` (or `-h`, or just `nsauditor-ai help`) for a quick reference of subcommands, flags, env vars, and worked examples — works without a license key configured. `--version` / `-v` prints `nsauditor-ai <version>` and exits 0.
|
|
682
464
|
|
|
683
465
|
| Flag | Description | Default |
|
|
684
466
|
|---|---|---|
|
|
@@ -698,7 +480,7 @@ nsauditor-ai --version (or -v, or `version`)
|
|
|
698
480
|
| `--compliance <fw>` | Compliance framework to map findings into (e.g. `soc2`). **Enterprise license required.** See `@nsasoft/nsauditor-ai-ee` README for supported frameworks | — |
|
|
699
481
|
| `--compliance-scope <path>` | Optional JSON file describing the assessment scope (passed to the compliance engine for cover-page attestation) | — |
|
|
700
482
|
| `--help`, `-h` | Print usage block (subcommands, flags, env vars, examples) and exit 0 | — |
|
|
701
|
-
| `--version`, `-v` | Print `nsauditor-ai <version>` and exit 0
|
|
483
|
+
| `--version`, `-v` | Print `nsauditor-ai <version>` and exit 0 | — |
|
|
702
484
|
|
|
703
485
|
\* Either `--host` or `--host-file` is required.
|
|
704
486
|
|
|
@@ -930,7 +712,7 @@ No license key? Everything in this repository works perfectly without one. The C
|
|
|
930
712
|
|
|
931
713
|
## Tests
|
|
932
714
|
|
|
933
|
-
Run all
|
|
715
|
+
Run all 925+ tests:
|
|
934
716
|
|
|
935
717
|
```bash
|
|
936
718
|
npm test
|
package/bin/nsauditor-ai-mcp.mjs
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
// CE 0.1.37 (SECURITY): delegate to startStdioServer() so the auth
|
|
3
|
+
// check + license verification + rotation warnings actually run.
|
|
4
|
+
// Pre-0.1.37 this file inlined `createServer() + server.connect()`,
|
|
5
|
+
// which silently bypassed the entire startup block in mcp_server.mjs
|
|
6
|
+
// (it was guarded by an argv[1].endsWith('mcp_server.mjs') check that
|
|
7
|
+
// only matched when invoked directly, never via this shim). Result:
|
|
8
|
+
// every Claude Desktop session ran unauthenticated and tier-stuck-at-CE.
|
|
9
|
+
import { startStdioServer } from '../mcp_server.mjs';
|
|
4
10
|
|
|
5
|
-
|
|
6
|
-
const transport = new StdioServerTransport();
|
|
7
|
-
await server.connect(transport);
|
|
11
|
+
await startStdioServer();
|
package/mcp_server.mjs
CHANGED
|
@@ -493,16 +493,22 @@ export function createServer() {
|
|
|
493
493
|
}
|
|
494
494
|
|
|
495
495
|
// ---------------------------------------------------------------------------
|
|
496
|
-
//
|
|
496
|
+
// Stdio entry point — used by bin/nsauditor-ai-mcp.mjs AND `node mcp_server.mjs`
|
|
497
497
|
// ---------------------------------------------------------------------------
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
498
|
+
//
|
|
499
|
+
// CE 0.1.37 (SECURITY): this used to be guarded by a brittle
|
|
500
|
+
// `process.argv[1].endsWith('mcp_server.mjs')` check. The bin shim
|
|
501
|
+
// (which Claude Desktop spawns) sets argv[1] to `nsauditor-ai-mcp.mjs`,
|
|
502
|
+
// so the guard was false and the entire startup block — auth check,
|
|
503
|
+
// license verification, rotation warnings — was SKIPPED. Result: Claude
|
|
504
|
+
// Desktop's MCP child ran unauthenticated, with _tier stuck at the CE
|
|
505
|
+
// default, regardless of the operator's installed license. Customers
|
|
506
|
+
// paying for Pro/Enterprise saw "Current tier: CE" responses and lost
|
|
507
|
+
// MCP access to gated tools entirely.
|
|
508
|
+
//
|
|
509
|
+
// Fix: extract the startup into an exported function. The bin shim now
|
|
510
|
+
// calls it explicitly, so the auth + license path runs every time.
|
|
511
|
+
export async function startStdioServer() {
|
|
506
512
|
// EE-SEC.1: enforce MCP server authentication BEFORE accepting any
|
|
507
513
|
// tool calls. Pre-fold any process running as the operator could
|
|
508
514
|
// spawn the server and call Pro/Enterprise tools — including the
|
|
@@ -589,4 +595,16 @@ if (isMainModule) {
|
|
|
589
595
|
const server = createServer();
|
|
590
596
|
const transport = new StdioServerTransport();
|
|
591
597
|
await server.connect(transport);
|
|
598
|
+
return server;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// Backward-compat: still callable as `node mcp_server.mjs` directly.
|
|
602
|
+
const isMainModule =
|
|
603
|
+
typeof process !== 'undefined' &&
|
|
604
|
+
process.argv[1] &&
|
|
605
|
+
(process.argv[1].endsWith('mcp_server.mjs') ||
|
|
606
|
+
process.argv[1].endsWith('mcp_server'));
|
|
607
|
+
|
|
608
|
+
if (isMainModule) {
|
|
609
|
+
await startStdioServer();
|
|
592
610
|
}
|