nsauditor-ai 0.2.42 → 0.2.43
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 +51 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,6 +17,8 @@ NSAuditor AI is the open-source core of a privacy-first security intelligence pl
|
|
|
17
17
|
|
|
18
18
|
## What's New
|
|
19
19
|
|
|
20
|
+
**The pack-signing commands land in the CLI — reachable, not yet proven (CE 0.2.43 / Enterprise 0.38.0).** `nsauditor-ai compliance sign-pack --manifest <envelope>` signs a chain-of-custody envelope with an operator-held Ed25519 key; `compliance verify-pack` establishes authorship from it — via `--registry` (your identity registry, with revocation and validity checked **as at signing time**) or `--public-key` (which discloses in its own output that those checks did not run). Both are thin forwards: Enterprise owns every decision and refusal, CE contributes the flags and the exit code. **Verify does more than the signature** — it recomputes every `artifacts[].sha256` against disk, so a signed pack whose report was edited returns a failure with the signature still reading VERIFIED. Exit **0** verified · **1** a violation · **2** the run could not measure, and the third is never a failure. Requires the Enterprise package; an auditor can also verify offline with `openssl` and nothing of ours, because the exact signed bytes ship beside the signature. **⚠️ Also a correction affecting 0.2.42/0.37.0:** a **gzipped** KEV/EPSS store — the default shape, since FIRST distributes EPSS only as `.csv.gz` — loaded with ZERO entries, so every finding reported *no store* rather than an exploit band. Misdiagnosis and silent degradation, **not** a false security verdict: findings carried a visible no-store marker throughout. Compression is now decided by file content rather than by filename.
|
|
21
|
+
|
|
20
22
|
**The `feed` commands: offline CVE data can be hand-carried (CE 0.2.42 / Enterprise 0.37.0).** `nsauditor-ai feed bundle` merges the NVD feed files you downloaded on a connected host into one portable archive; `feed import` reads one into the offline store on an isolated host — delivered as a **restricted** distribution rather than a public `npm install`, and amd64 only. The implementations are Enterprise-side (**requires `@nsasoft/nsauditor-ai-ee` >= 0.37.0**); the commands, flags and usage text are here, because this is the package with the `bin`. Optional `--kev` / `--epss` carry **your own** downloads from CISA and FIRST inside the archive, and `--extras-dir` places them on import and prints the environment lines to set — **no exploit data ships with either package**. `bundle` bundles the FEEDS YOU DOWNLOADED, never "your database": the offline store is a lossy derivation of an NVD feed and cannot be turned back into one. Import now names **why** it skipped records — about a quarter of a real NVD year file is skipped by design (withdrawn CVEs, entries with no CPE data) and a bare `skipped 9353` reads as data loss; malformed records are called out separately because those are **not** expected. ⚠️ **A bundle is integrity-checked, not authenticated** — the recorded SHA-256 detects alteration in transit but cannot establish authorship, because it travels inside the archive it covers. Also here: **`--flag=value` is now refused by name** instead of being parsed as a valueless flag with the value discarded, which made `--severity=high` run a default-severity scan and report success — a wrong answer that looked like a right one; and the **mDNS module-shape fallback was a TDZ self-reference**, so it never once fell back. **The air-gap delivery claims are earned back at this release**, with two conditions that travel with them: the dependency-complete bundle is a **restricted** distribution rather than a public install, and it is **amd64** only — no arm64 image is published.
|
|
21
23
|
|
|
22
24
|
**The compliance report now verifies the signatures it renders (CE 0.2.41 / Enterprise 0.36.0).** Paired with Enterprise 0.36.0 — **no CE behaviour change; the peer floor stays `>=0.2.40`, unraised, because nothing in this cycle needs new CE code.** Enterprise-side, a registry member may now carry the approver's public key beside its fingerprint, and when it does, every suppression signature in a compliance report is cryptographically checked — the Ed25519 suppression-signing capability this exercises is **proven as of Enterprise 0.36.0**, its verification gate having run against the published bytes and passed with a tamper negative control, and verified for approvers whose registry entry carries **key material**. Verdicts name the exact bytes they verified, a revoked key's bytes are still checked so signing-after-revocation becomes a cryptographic finding, and a MISSING verdict reads "not checked" rather than "failed" — a report must not accuse an operator of forgery for not having migrated. **Ed25519 suppression signing was `not yet proven` when this shipped**: it shipped the code that made the verification gate satisfiable, and that gate then passed at Enterprise 0.36.0.
|
|
@@ -122,7 +124,8 @@ How Marketplace fulfillment works (ZDE and air-gap preserved — no runtime AWS
|
|
|
122
124
|
| **Enterprise — integration + deployment** | | | |
|
|
123
125
|
| GRC connectors — Vanta + Drata + Secureframe push (scan-time, opt-in) | — | — | ✅ |
|
|
124
126
|
| Tabletop simulation + SIEM correlation — built, **not reachable** (no caller) | — | — | 🚧 |
|
|
125
|
-
| Air-gapped **operation** once installed — offline licence validation, offline CVE matching under `NSAUDITOR_OFFLINE_ONLY=1
|
|
127
|
+
| Air-gapped **operation** once installed — offline licence validation (local ES256, no callback, every tier) and offline CVE matching under `NSAUDITOR_OFFLINE_ONLY=1`, which is the **Pro** intelligence engine. The `feed bundle` / `feed import` hand-carry pipeline (EE 0.37.0) moves the NVD feeds **you downloaded**; it needs the Enterprise **package** installed but is not licence-gated, so a Pro licensee can run it. | — | ✅ | ✅ |
|
|
128
|
+
| Air-gapped **DELIVERY** — the dependency-complete offline installation tarball, install script and checksums (EE 0.37.0), distributed **restricted**, amd64 only. No container image bundle ships and arm64 images remain WITHDRAWN. | — | — | ✅ |
|
|
126
129
|
|
|
127
130
|
**This repository is the Community Edition** — fully functional, MIT-licensed, no restrictions, no telemetry. Pro and Enterprise features ship via the [`@nsasoft/nsauditor-ai-ee`](https://www.nsauditor.com/ai/pricing) package and install alongside the CE binary once licensed.
|
|
128
131
|
|
|
@@ -264,7 +267,7 @@ Results land in `./out/<host>_<timestamp>/`:
|
|
|
264
267
|
|
|
265
268
|
**28 enterprise plugins: 27 cloud auditors across AWS, GCP and Azure substrate, plus **`1023 Zero Trust Assessment`**, which scores zero-trust posture (segmentation, encryption-in-transit, identity, lateral-movement risk) from a **network-host** scan** — all mapped to AICPA Trust Services Criteria 2017 (10 covered + 4 partial controls). EE plugins live in the disjoint 1000+ ID range; CE reserves 001-099. Once licensed, the EE package installs alongside the CE binary and discovers automatically. A cloud `--host` pass auto-scopes on `cloudProvider`, which only the 27 declare, so `1023` never runs on a cloud pass. It runs on a network-host scan with the full plugin set — measured on the shipped CLI, selecting it by id on its own does not work, because it requires the host to be confirmed up by a discovery plugin.
|
|
266
269
|
|
|
267
|
-
→ **[Watch a sample scan run end-to-end](https://www.nsauditor.com/ai/docs/sample-scan/)** — synthetic Acme Corp AWS account + home-office router. Real real scan output, no signup required. See the transitive SG chain reachability finding, the multi-region GuardDuty audit, the dnsmasq CVE detection, and what the
|
|
270
|
+
→ **[Watch a sample scan run end-to-end](https://www.nsauditor.com/ai/docs/sample-scan/)** — synthetic Acme Corp AWS account + home-office router. Real real scan output, no signup required. See the transitive SG chain reachability finding, the multi-region GuardDuty audit, the dnsmasq CVE detection, and what the evidence pack actually looks like.
|
|
268
271
|
|
|
269
272
|
→ **[Buy NSAuditor AI Enterprise Edition](https://www.nsauditor.com/ai/enterprise/)** · $2k / $5k / $10k+ per year · 5 / 25 / unlimited seats · onboarding call included.
|
|
270
273
|
|
|
@@ -678,7 +681,7 @@ nsauditor-ai license <--status | --capabilities | --plugins>
|
|
|
678
681
|
nsauditor-ai security <set|delete|list|get> <KEY>
|
|
679
682
|
nsauditor-ai validate
|
|
680
683
|
nsauditor-ai feed bundle --from <dir-of-NVD-feeds> --out <bundle.json.gz> [--kev <f>] [--epss <f>]
|
|
681
|
-
nsauditor-ai feed import --file <feed-or-bundle> [--cache-dir <d>] [--extras-dir <d>]
|
|
684
|
+
nsauditor-ai feed import --file <feed-or-bundle> [--cache-dir <d>] [--extras-dir <d>] # the feeds you downloaded
|
|
682
685
|
nsauditor-ai compliance <attest|suppress|review|renew|keygen> (Enterprise)
|
|
683
686
|
nsauditor-ai mcp
|
|
684
687
|
nsauditor-ai --help (or -h, or `help`)
|
package/cli.mjs
CHANGED
|
@@ -762,6 +762,12 @@ export async function parseArgs(argv) {
|
|
|
762
762
|
suppressionId: str('id'),
|
|
763
763
|
expiresInDays: str('expires-in-days'),
|
|
764
764
|
attestationLevel: str('attestation-level'),
|
|
765
|
+
// Pack signing (EE 0.38.0). `--manifest` names ONE chain-of-custody envelope, because a
|
|
766
|
+
// signature is scoped to one framework's envelope and the framework is read from the file
|
|
767
|
+
// being signed — not guessed from a directory that holds seven of them.
|
|
768
|
+
manifest: str('manifest'),
|
|
769
|
+
publicKey: str('public-key') ?? str('public_key'),
|
|
770
|
+
registry: str('registry'),
|
|
765
771
|
compensatingControl: str('compensating-control'),
|
|
766
772
|
force: !!get('force'),
|
|
767
773
|
};
|
|
@@ -2354,7 +2360,8 @@ Docs: https://www.nsauditor.com/ai/ | Pricing: https://www.nsauditor.com/ai/
|
|
|
2354
2360
|
// the three-part gate runs against the published registry bytes and the hedges
|
|
2355
2361
|
// flip at N+1. If you are reading this while editing marketing copy, the answer
|
|
2356
2362
|
// is still "not yet".
|
|
2357
|
-
if (sub === 'suppress' || sub === 'review' || sub === 'renew' || sub === 'keygen'
|
|
2363
|
+
if (sub === 'suppress' || sub === 'review' || sub === 'renew' || sub === 'keygen'
|
|
2364
|
+
|| sub === 'sign-pack' || sub === 'verify-pack') {
|
|
2358
2365
|
let ee;
|
|
2359
2366
|
try {
|
|
2360
2367
|
ee = await import('@nsasoft/nsauditor-ai-ee');
|
|
@@ -2381,6 +2388,49 @@ Docs: https://www.nsauditor.com/ai/ | Pricing: https://www.nsauditor.com/ai/
|
|
|
2381
2388
|
+ 'signing happens here, at approval time.');
|
|
2382
2389
|
process.exit(0);
|
|
2383
2390
|
}
|
|
2391
|
+
if (sub === 'sign-pack' || sub === 'verify-pack') {
|
|
2392
|
+
// ⚠️ THIN FORWARD, LIKE EVERY VERB ABOVE IT. EE decides what a manifest is, whether the
|
|
2393
|
+
// key may be used, what gets written and what every verdict means. This block builds an
|
|
2394
|
+
// options object, prints what EE returns, and exits.
|
|
2395
|
+
if (!A.manifest) {
|
|
2396
|
+
console.error(`compliance ${sub} requires --manifest <scan_chain_of_custody_<framework>.json>`);
|
|
2397
|
+
process.exit(2);
|
|
2398
|
+
}
|
|
2399
|
+
if (sub === 'sign-pack') {
|
|
2400
|
+
const out = await ee.signPackCommand({ manifestPath: A.manifest }, {
|
|
2401
|
+
// Same provenance discipline as `suppress`: only THIS line knows the reference came
|
|
2402
|
+
// from an environment variable, so only this line can make a refusal name it.
|
|
2403
|
+
signingKeyRaw: process.env.NSAUDITOR_SIGNING_KEY || undefined,
|
|
2404
|
+
signingKeyFrom: 'environment',
|
|
2405
|
+
attestationLevel: A.attestationLevel || undefined,
|
|
2406
|
+
});
|
|
2407
|
+
console.log(`signed ${path.basename(A.manifest)} — ${out.record.subject.framework} / ${out.record.subject.scanId}`);
|
|
2408
|
+
console.log(` wrote ${out.recordPath}`);
|
|
2409
|
+
console.log(` wrote ${out.payloadPath} (the exact bytes signed — an auditor verifies THIS file)`);
|
|
2410
|
+
console.log(' this signature covers THIS framework\'s envelope and the four artifacts it '
|
|
2411
|
+
+ 'enumerates — not the directory, and not the pack.');
|
|
2412
|
+
process.exit(0);
|
|
2413
|
+
}
|
|
2414
|
+
let publicKeyPem;
|
|
2415
|
+
if (A.publicKey) {
|
|
2416
|
+
try {
|
|
2417
|
+
publicKeyPem = await fsp.readFile(A.publicKey, 'utf8');
|
|
2418
|
+
} catch (e) {
|
|
2419
|
+
console.error(`cannot read --public-key ${A.publicKey}: ${e.code ?? e.message}`);
|
|
2420
|
+
process.exit(2);
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2423
|
+
// Two arms, and EE refuses both-at-once rather than applying a silent precedence — an
|
|
2424
|
+
// operator must be able to tell which trust anchor was actually consulted.
|
|
2425
|
+
const out = await ee.verifyPackCommand({
|
|
2426
|
+
manifestPath: A.manifest, publicKeyPem, registryPath: A.registry || undefined,
|
|
2427
|
+
});
|
|
2428
|
+
for (const line of out.lines) console.log(line);
|
|
2429
|
+
// ⚠️ EE OWNS THE EXIT CODE. 0 verified · 1 a violation · 2 could not measure — and the
|
|
2430
|
+
// third is NOT a failure. Collapsing it here would tell an auditor their evidence failed
|
|
2431
|
+
// verification when the truth is that nothing was checked.
|
|
2432
|
+
process.exit(out.exitCode);
|
|
2433
|
+
}
|
|
2384
2434
|
if (sub === 'review') {
|
|
2385
2435
|
const { rows, summary } = await ee.reviewCommand({ rootDir: complianceHistory });
|
|
2386
2436
|
console.log(`Suppressions: ${summary.total} total · ${summary.active} active · `
|