nsauditor-ai 0.1.36 → 0.1.37
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 +32 -0
- package/bin/nsauditor-ai-mcp.mjs +9 -5
- package/mcp_server.mjs +27 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,38 @@ NSAuditor AI is the open-source core of a privacy-first security intelligence pl
|
|
|
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 (0.1.37) — 🛑 SECURITY FIX: bin shim bypassed auth + license verification
|
|
19
|
+
|
|
20
|
+
**Affects all installations using Claude Desktop (or any MCP client invoking the published `nsauditor-ai-mcp` binary).** Pre-0.1.37, the bin shim at `bin/nsauditor-ai-mcp.mjs` directly called `createServer() + server.connect()` and never invoked the startup block in `mcp_server.mjs` that runs:
|
|
21
|
+
|
|
22
|
+
1. **`authorizeMcpServerStartup()`** — the `NSA_MCP_AUTH_KEY` enforcement we shipped in EE-SEC.1 (CE 0.1.31). Skipped means **any process with stdio access to the spawned MCP child could call the tools without supplying the auth key**.
|
|
23
|
+
2. **`await loadLicense()`** — JWT verification of the operator's license key. Skipped means `_tier` stuck at the module-load CE default, so paid Pro/Enterprise customers saw "Current tier: CE" responses and lost MCP access to gated tools entirely.
|
|
24
|
+
3. Rotation cadence warnings, keychain-locked diagnostics — all silent.
|
|
25
|
+
|
|
26
|
+
**Root cause**: an `argv[1].endsWith('mcp_server.mjs')` guard in `mcp_server.mjs` only matched when the server was invoked directly as `node mcp_server.mjs`. Claude Desktop spawns via the published bin (`nsauditor-ai-mcp`), so the guard was always false in production. The guard existed so that test imports of the module wouldn't auto-start the server — but the fix should have been to extract the startup into a function the bin shim explicitly calls.
|
|
27
|
+
|
|
28
|
+
**Detection**: in 0.1.36 you could spot this if you noticed your MCP responses said `Current tier: Community Edition (CE)` despite `nsauditor-ai mcp tier` from the shell saying `enterprise`. The disagreement was the 0.1.37 bug surfacing.
|
|
29
|
+
|
|
30
|
+
**Fix in 0.1.37**:
|
|
31
|
+
- Extracted the entire startup sequence into `export async function startStdioServer()` in `mcp_server.mjs`.
|
|
32
|
+
- `bin/nsauditor-ai-mcp.mjs` now imports and awaits `startStdioServer()`. Every Claude Desktop spawn now runs the auth check and license verification it always should have.
|
|
33
|
+
- Regression test (`tests/mcp_bin_startup.test.mjs`) spawns the bin shim with no auth key in env and asserts the auth check refuses startup. If the bin shim ever regresses to bypassing startup again, this test fails.
|
|
34
|
+
|
|
35
|
+
**Action required**: upgrade immediately.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install -g nsauditor-ai@0.1.37
|
|
39
|
+
# Restart Claude Desktop. Verify with:
|
|
40
|
+
# - Real MCP call from Claude → response should say "Current tier: Enterprise" (or Pro)
|
|
41
|
+
# - nsauditor-ai mcp verify-call <uuid> ← the 0.1.36 sentinel still works
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Threat model note**: a process needing stdio access to your Claude Desktop MCP child already had to be running as your user (or able to write to your `~/Library/Application Support/Claude/` config). The auth-bypass exposure is *defense-in-depth degradation*, not "anyone on the internet can call your scanner." But the tier-stuck-at-CE bug definitely cost paying customers actual functionality, and SOC 2 evidence generated from MCP-routed CE-tier responses would fail audit because it lacked enterprise-tier checks.
|
|
45
|
+
|
|
46
|
+
Thanks to the customer who caught this in the wild while we were chasing what looked like a Claude Desktop hallucination — turned out the bug was on our side.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
18
50
|
## What's New (0.1.36) — cryptographic per-call sentinel UUID (hallucination becomes mathematically detectable)
|
|
19
51
|
|
|
20
52
|
The version-block comparison shipped in 0.1.34/0.1.35 catches lazy hallucinations, but a sufficiently capable AI client can still copy a previously-seen version block from chat context and pass off a fabricated response. **0.1.36 closes that gap** with a per-call cryptographic sentinel that the AI cannot fake.
|
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
|
}
|