nsauditor-ai 0.1.1 → 0.1.3
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 +6 -3
- package/cli.mjs +1 -1
- package/docs/EULA-nsauditor-ai.md +1 -5
- package/mcp_server.mjs +14 -10
- package/package.json +1 -1
- package/plugin_manager.mjs +2 -2
- package/plugins/os_detector.mjs +1 -1
- package/plugins/snmp_scanner.mjs +1 -1
- package/plugins/ssh_scanner.mjs +0 -7
- package/utils/license.mjs +3 -5
- package/utils/sarif.mjs +1 -1
package/README.md
CHANGED
|
@@ -271,18 +271,21 @@ Add this to your `claude_desktop_config.json` (Settings → Developer → Edit C
|
|
|
271
271
|
"mcpServers": {
|
|
272
272
|
"nsauditor-ai": {
|
|
273
273
|
"command": "npx",
|
|
274
|
-
"args": ["nsauditor-ai-mcp"],
|
|
274
|
+
"args": ["--package=nsauditor-ai", "nsauditor-ai-mcp"],
|
|
275
275
|
"env": {
|
|
276
276
|
"AI_PROVIDER": "claude",
|
|
277
277
|
"ANTHROPIC_API_KEY": "your-key-here",
|
|
278
|
-
"NSA_ALLOW_ALL_HOSTS": "1"
|
|
278
|
+
"NSA_ALLOW_ALL_HOSTS": "1",
|
|
279
|
+
"PLUGIN_TIMEOUT_MS": "5000"
|
|
279
280
|
}
|
|
280
281
|
}
|
|
281
282
|
}
|
|
282
283
|
}
|
|
283
284
|
```
|
|
284
285
|
|
|
285
|
-
|
|
286
|
+
- `NSA_ALLOW_ALL_HOSTS=1` — required to scan private/RFC 1918 addresses (e.g., `192.168.x.x`)
|
|
287
|
+
- `PLUGIN_TIMEOUT_MS=5000` — reduces per-plugin timeout to 5s so the full scan completes within Claude Desktop's 60s MCP limit
|
|
288
|
+
- `AI_PROVIDER` and API key — optional, enables AI-powered analysis of scan results
|
|
286
289
|
|
|
287
290
|
### Claude Code Setup
|
|
288
291
|
|
package/cli.mjs
CHANGED
|
@@ -685,7 +685,7 @@ async function main() {
|
|
|
685
685
|
if (cmd === 'license') {
|
|
686
686
|
const { getTierFromEnv } = await import('./utils/license.mjs');
|
|
687
687
|
const { resolveCapabilities } = await import('./utils/capabilities.mjs');
|
|
688
|
-
// TODO
|
|
688
|
+
// TODO: replace getTierFromEnv() with loadLicense() for full license validation
|
|
689
689
|
const tier = getTierFromEnv();
|
|
690
690
|
const caps = resolveCapabilities(tier);
|
|
691
691
|
const key = process.env.NSAUDITOR_LICENSE_KEY;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# NSAUDITOR AI — END USER LICENSE AGREEMENT (EULA)
|
|
2
2
|
|
|
3
3
|
**Nsasoft US LLC**
|
|
4
|
-
**Effective Date:
|
|
4
|
+
**Effective Date: April 7, 2026**
|
|
5
5
|
**Version: 2.0**
|
|
6
6
|
|
|
7
7
|
---
|
|
@@ -317,8 +317,4 @@ Website: https://www.nsauditor.com/ai/
|
|
|
317
317
|
|
|
318
318
|
---
|
|
319
319
|
|
|
320
|
-
*This document is a draft template for review purposes. Nsasoft US LLC should have this Agreement reviewed by a licensed attorney before publication. This does not constitute legal advice.*
|
|
321
|
-
|
|
322
|
-
---
|
|
323
|
-
|
|
324
320
|
**END OF LICENSE AGREEMENT**
|
package/mcp_server.mjs
CHANGED
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
// import { createServer, toolHandlers } from './mcp_server.mjs' — for testing
|
|
9
9
|
|
|
10
10
|
import { createRequire } from 'node:module';
|
|
11
|
+
import { dirname } from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
15
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
12
16
|
import { resolveAndValidate } from './utils/net_validation.mjs';
|
|
13
17
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -25,15 +29,12 @@ const { version: TOOL_VERSION } = _require('./package.json');
|
|
|
25
29
|
// License tier & capability resolution (module-level, overridable for tests)
|
|
26
30
|
// ---------------------------------------------------------------------------
|
|
27
31
|
|
|
28
|
-
// TODO
|
|
29
|
-
// and wire the returned tier here. Until then, pro_* prefix grants Pro tier without verification.
|
|
32
|
+
// TODO: replace getTierFromEnv() with loadLicense() for full license validation.
|
|
30
33
|
let _tier = getTierFromEnv();
|
|
31
34
|
let _capabilities = resolveCapabilities(_tier);
|
|
32
35
|
|
|
33
36
|
/**
|
|
34
37
|
* @internal Test-only. Override tier without touching env vars.
|
|
35
|
-
* Do NOT use in production code. When JWT license validation lands (Phase 2),
|
|
36
|
-
* this function will be removed or guarded by NODE_ENV !== 'production'.
|
|
37
38
|
*/
|
|
38
39
|
export function _setTier(tier) {
|
|
39
40
|
if (process.env.NODE_ENV === 'production') throw new Error('_setTier is test-only and disabled in production');
|
|
@@ -68,7 +69,7 @@ let _nvdClient = null;
|
|
|
68
69
|
async function getPluginManager() {
|
|
69
70
|
if (_pluginManager) return _pluginManager;
|
|
70
71
|
const { default: PluginManager } = await import('./plugin_manager.mjs');
|
|
71
|
-
_pluginManager = await PluginManager.create(
|
|
72
|
+
_pluginManager = await PluginManager.create(`${__dirname}/plugins`);
|
|
72
73
|
return _pluginManager;
|
|
73
74
|
}
|
|
74
75
|
|
|
@@ -197,11 +198,14 @@ export async function validateHost(host) {
|
|
|
197
198
|
throw new Error('Scanning loopback, link-local, or metadata addresses is not allowed via MCP');
|
|
198
199
|
}
|
|
199
200
|
|
|
200
|
-
// DNS resolution check — catches rebinding, decimal/octal IPs, IPv6-mapped addrs
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
201
|
+
// DNS resolution check — catches rebinding, decimal/octal IPs, IPv6-mapped addrs.
|
|
202
|
+
// NSA_ALLOW_ALL_HOSTS=1 bypasses RFC 1918 checks for local network auditing.
|
|
203
|
+
if (!process.env.NSA_ALLOW_ALL_HOSTS) {
|
|
204
|
+
try {
|
|
205
|
+
await resolveAndValidate(h);
|
|
206
|
+
} catch (err) {
|
|
207
|
+
throw new Error('Scanning loopback, link-local, or metadata addresses is not allowed via MCP');
|
|
208
|
+
}
|
|
205
209
|
}
|
|
206
210
|
return h;
|
|
207
211
|
}
|
package/package.json
CHANGED
package/plugin_manager.mjs
CHANGED
|
@@ -378,7 +378,7 @@ export class PluginManager {
|
|
|
378
378
|
const mgr = new PluginManager(baseDir);
|
|
379
379
|
mgr.plugins = rawPlugins;
|
|
380
380
|
// Resolve capabilities from env tier at load time — prevents permissive fallback.
|
|
381
|
-
// TODO
|
|
381
|
+
// TODO: replace getTierFromEnv() with loadLicense() result here.
|
|
382
382
|
mgr._resolvedCapabilities = resolveCapabilities(getTierFromEnv());
|
|
383
383
|
vlog("PluginManager initialized successfully");
|
|
384
384
|
return mgr;
|
|
@@ -643,7 +643,7 @@ export class PluginManager {
|
|
|
643
643
|
_hasCapabilities(plugin, capabilities) {
|
|
644
644
|
if (!plugin.requiredCapabilities?.length) return true;
|
|
645
645
|
// Fall back to capabilities resolved at load time — never "allow all".
|
|
646
|
-
//
|
|
646
|
+
// Capabilities resolved at load time — updated when license validation lands.
|
|
647
647
|
const caps = capabilities ?? this._resolvedCapabilities ?? {};
|
|
648
648
|
return plugin.requiredCapabilities.every(cap => Boolean(caps[cap]));
|
|
649
649
|
}
|
package/plugins/os_detector.mjs
CHANGED
|
@@ -93,7 +93,7 @@ function evidenceRow(info, port = null, proto = "os-detector", banner = null) {
|
|
|
93
93
|
|
|
94
94
|
function looksLikeAppleHost(s) {
|
|
95
95
|
const host = String(s || "").toLowerCase();
|
|
96
|
-
// iphone-of-
|
|
96
|
+
// iphone-of-alice.local, Alices-iPad.local, Alices-iMac.local, MacBook-Air.local, apple-tv.local, etc.
|
|
97
97
|
return /(iphone|ipad|ipod|imac|macbook|apple.?tv)/i.test(host);
|
|
98
98
|
}
|
|
99
99
|
|
package/plugins/snmp_scanner.mjs
CHANGED
|
@@ -9,7 +9,7 @@ export const snmpCommunities = process.env.SNMP_COMMUNITY
|
|
|
9
9
|
: DEFAULT_COMMUNITIES;
|
|
10
10
|
const oidTable = {
|
|
11
11
|
default: [1, 3, 6, 1, 2, 1, 1, 1, 0], // sysDescr
|
|
12
|
-
epsonShortName: [1, 3, 6, 1, 2, 1, 1, 5, 0], //
|
|
12
|
+
epsonShortName: [1, 3, 6, 1, 2, 1, 1, 5, 0], // sysName '1.3.6.1.2.1.1.5.0'
|
|
13
13
|
epsonModel: [1, 3, 6, 1, 4, 1, 1248, 1, 1, 3, 1, 29, 3, 1, 45, 0], // Epson model OID
|
|
14
14
|
epsonSerial: [1, 3, 6, 1, 4, 1, 1248, 1, 2, 2, 1, 1, 1, 4, 1], // Epson serial number
|
|
15
15
|
epsonVersions: [1, 3, 6, 1, 2, 1, 2, 2, 1, 2, 1], // Hardware and firmware versions
|
package/plugins/ssh_scanner.mjs
CHANGED
|
@@ -365,14 +365,7 @@ export default {
|
|
|
365
365
|
* @returns {Promise<object>} result object (manager wraps with id/name)
|
|
366
366
|
*/
|
|
367
367
|
async run(host, port = 22, options = {}) {
|
|
368
|
-
console.log(`Running SSH Scanner on ${host}:${port}`);
|
|
369
368
|
const res = await readSshBanner(host, port, options?.timeoutMs || 1500);
|
|
370
|
-
// Mirror your other plugins’ console style (manager will also print the wrapped result)
|
|
371
|
-
console.log("SSH Scanner Result:", JSON.stringify({
|
|
372
|
-
id: this.id,
|
|
373
|
-
name: this.name,
|
|
374
|
-
result: res
|
|
375
|
-
}, null, 2));
|
|
376
369
|
return res; // manager expects only the "result" object
|
|
377
370
|
}
|
|
378
371
|
};
|
package/utils/license.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// utils/license.mjs
|
|
2
|
-
// CE stub
|
|
2
|
+
// CE stub — full license validation coming in a future release.
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Parse tier from NSAUDITOR_LICENSE_KEY environment variable.
|
|
6
6
|
* Stub uses key prefix: pro_* → 'pro', enterprise_* → 'enterprise'.
|
|
7
|
-
* Phase 2 roadmap replaces this with offline jose ES256 JWT verification.
|
|
8
7
|
*/
|
|
9
8
|
export function getTierFromEnv() {
|
|
10
9
|
const key = process.env.NSAUDITOR_LICENSE_KEY;
|
|
@@ -16,7 +15,6 @@ export function getTierFromEnv() {
|
|
|
16
15
|
|
|
17
16
|
/**
|
|
18
17
|
* Validate a license key string.
|
|
19
|
-
* Phase 2 roadmap: replace with jose.jwtVerify() against embedded ECDSA P-256 public key.
|
|
20
18
|
* Gracefully degrades to CE on any failure — never throws.
|
|
21
19
|
*
|
|
22
20
|
* @param {string|undefined} keyStr
|
|
@@ -24,6 +22,6 @@ export function getTierFromEnv() {
|
|
|
24
22
|
*/
|
|
25
23
|
export async function loadLicense(keyStr) {
|
|
26
24
|
if (!keyStr) return { valid: false, tier: 'ce', reason: 'no key provided' };
|
|
27
|
-
// TODO
|
|
28
|
-
return { valid: false, tier: 'ce', reason: '
|
|
25
|
+
// TODO: implement full license validation
|
|
26
|
+
return { valid: false, tier: 'ce', reason: 'license validation not yet implemented' };
|
|
29
27
|
}
|
package/utils/sarif.mjs
CHANGED
|
@@ -8,7 +8,7 @@ const { version: TOOL_VERSION } = require('../package.json');
|
|
|
8
8
|
const SARIF_VERSION = '2.1.0';
|
|
9
9
|
const SARIF_SCHEMA = 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json';
|
|
10
10
|
const TOOL_NAME = 'nsauditor';
|
|
11
|
-
const TOOL_URI = 'https://github.com/nsasoft/nsauditor-
|
|
11
|
+
const TOOL_URI = 'https://github.com/nsasoft/nsauditor-ai';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Map nsauditor severity to SARIF level.
|