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 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
- Set `NSA_ALLOW_ALL_HOSTS=1` if you need to scan private/RFC 1918 addresses (e.g., `192.168.x.x`). The `AI_PROVIDER` and key variables are optional — they enable AI-powered analysis of scan results.
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 (Phase 2): replace getTierFromEnv() with loadLicense() for full JWT verification
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: [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 (Phase 2): replace getTierFromEnv() with loadLicense(process.env.NSAUDITOR_LICENSE_KEY)
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('./plugins');
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
- try {
202
- await resolveAndValidate(h);
203
- } catch (err) {
204
- throw new Error('Scanning loopback, link-local, or metadata addresses is not allowed via MCP');
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nsauditor-ai",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Modular AI-assisted network security audit platform — Community Edition",
5
5
  "type": "module",
6
6
  "private": false,
@@ -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 (Phase 2): replace getTierFromEnv() with loadLicense() result here.
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
- // TODO (Phase 2): _resolvedCapabilities will reflect JWT-verified tier.
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
  }
@@ -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-joe.local, ANAHITs-iPad.local, ANAHITs-iMac.local, MacBook-Air.local, apple-tv.local, etc.
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
 
@@ -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], // sysDescr EPSON6768F4 '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
@@ -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 implementation. Full ES256 JWT validation added in Phase 2 (roadmap).
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 (Phase 2): implement jose.jwtVerify with embedded public key
28
- return { valid: false, tier: 'ce', reason: 'JWT validation not yet implemented' };
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-plugin-manager';
11
+ const TOOL_URI = 'https://github.com/nsasoft/nsauditor-ai';
12
12
 
13
13
  /**
14
14
  * Map nsauditor severity to SARIF level.