@nodatachat/guard 2.1.0 → 2.2.0
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/dist/cli.js +68 -121
- package/dist/reporter.js +2 -2
- package/dist/types.d.ts +2 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -22,7 +22,6 @@ const activation_1 = require("./activation");
|
|
|
22
22
|
const code_scanner_1 = require("./code-scanner");
|
|
23
23
|
const db_scanner_1 = require("./db-scanner");
|
|
24
24
|
const reporter_1 = require("./reporter");
|
|
25
|
-
const registry_1 = require("./fixers/registry");
|
|
26
25
|
const scheduler_1 = require("./fixers/scheduler");
|
|
27
26
|
const VERSION = "2.0.0";
|
|
28
27
|
async function main() {
|
|
@@ -35,10 +34,8 @@ async function main() {
|
|
|
35
34
|
let failOn = null;
|
|
36
35
|
let outputDir = process.cwd();
|
|
37
36
|
let skipSend = false;
|
|
38
|
-
let fixMode = "none";
|
|
39
37
|
let schedulePreset;
|
|
40
38
|
let ciProvider;
|
|
41
|
-
let onlyFixers;
|
|
42
39
|
for (let i = 0; i < args.length; i++) {
|
|
43
40
|
switch (args[i]) {
|
|
44
41
|
case "--license-key":
|
|
@@ -63,13 +60,14 @@ async function main() {
|
|
|
63
60
|
skipSend = true;
|
|
64
61
|
break;
|
|
65
62
|
case "--fix-plan":
|
|
66
|
-
|
|
63
|
+
console.log("\n ⚠ --fix-plan is deprecated. Capsule provides recommendations only.\n Run without this flag to see recommendations.\n");
|
|
67
64
|
break;
|
|
68
65
|
case "--fix":
|
|
69
|
-
|
|
66
|
+
console.log("\n ⚠ --fix is deprecated. Capsule does not modify your code.\n Recommendations are provided in the scan output.\n");
|
|
70
67
|
break;
|
|
71
68
|
case "--fix-only":
|
|
72
|
-
|
|
69
|
+
i++;
|
|
70
|
+
console.log("\n ⚠ --fix-only is deprecated. Capsule provides recommendations only.\n");
|
|
73
71
|
break;
|
|
74
72
|
case "--schedule":
|
|
75
73
|
schedulePreset = args[++i] || "weekly";
|
|
@@ -283,102 +281,48 @@ async function main() {
|
|
|
283
281
|
console.log(" Your data never left your machine.");
|
|
284
282
|
console.log(" Diff the two files to verify.\n");
|
|
285
283
|
}
|
|
286
|
-
// ── Step 8:
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
scanResults: {
|
|
294
|
-
piiFields: piiFields.map(f => ({
|
|
295
|
-
table: f.table, column: f.column, pii_type: f.pii_type,
|
|
296
|
-
encrypted: f.encrypted, encryption_pattern: f.encryption_pattern,
|
|
297
|
-
})),
|
|
298
|
-
routes: routes.map(r => ({ path: r.path, has_auth: r.has_auth, auth_type: r.auth_type })),
|
|
299
|
-
secrets: secrets.map(s => ({
|
|
300
|
-
file: s.file, line: s.line, type: s.type,
|
|
301
|
-
severity: s.severity, is_env_interpolated: s.is_env_interpolated,
|
|
302
|
-
})),
|
|
303
|
-
rls: dbResult?.rls || [],
|
|
304
|
-
framework: stack.framework,
|
|
305
|
-
database: stack.database,
|
|
306
|
-
},
|
|
307
|
-
stack: {
|
|
308
|
-
framework: stack.framework,
|
|
309
|
-
database: stack.database,
|
|
310
|
-
language: "typescript",
|
|
311
|
-
hosting: "vercel",
|
|
312
|
-
},
|
|
313
|
-
};
|
|
314
|
-
const capsuleResult = await (0, registry_1.runCapsule)(fixerContext, {
|
|
315
|
-
mode: fixMode === "plan" ? "plan" : "apply",
|
|
316
|
-
fixers: onlyFixers,
|
|
317
|
-
dryRun: fixMode === "plan",
|
|
318
|
-
}, (msg) => log(ciMode, msg));
|
|
319
|
-
if (!ciMode) {
|
|
284
|
+
// ── Step 8: Recommendations ──
|
|
285
|
+
// NOTE: Capsule does NOT auto-fix code. We provide recommendations only.
|
|
286
|
+
// Applying fixes requires understanding of the target system — tables,
|
|
287
|
+
// relationships, business logic — and must be done by the customer's team.
|
|
288
|
+
if (!ciMode) {
|
|
289
|
+
const topFindings = metadata.findings || [];
|
|
290
|
+
if (topFindings.length > 0) {
|
|
320
291
|
console.log("");
|
|
321
292
|
console.log(" ══════════════════════════════════════");
|
|
322
|
-
console.log(
|
|
293
|
+
console.log(" RECOMMENDATIONS");
|
|
323
294
|
console.log(" ══════════════════════════════════════");
|
|
324
|
-
console.log(`
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
295
|
+
console.log(` ${topFindings.length} issues found. Top priorities:\n`);
|
|
296
|
+
const shown = topFindings.slice(0, 10);
|
|
297
|
+
for (const f of shown) {
|
|
298
|
+
const sev = f.severity === "critical" ? "\x1b[31mCRITICAL\x1b[0m"
|
|
299
|
+
: f.severity === "high" ? "\x1b[33mHIGH\x1b[0m"
|
|
300
|
+
: "\x1b[36mMEDIUM\x1b[0m";
|
|
301
|
+
console.log(` ${sev} ${f.title}`);
|
|
302
|
+
console.log(` \x1b[32m→ ${f.fix_suggestion}\x1b[0m`);
|
|
303
|
+
if (f.soc_control)
|
|
304
|
+
console.log(` SOC: ${f.soc_control}`);
|
|
305
|
+
console.log("");
|
|
329
306
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
console.log(` Proof hash: ${capsuleResult.proofHash.slice(0, 16)}...`);
|
|
333
|
-
console.log(" ──────────────────────────────────────");
|
|
334
|
-
// Print per-fixer summary
|
|
335
|
-
for (const plan of capsuleResult.plans) {
|
|
336
|
-
const icon = plan.actions.every(a => a.status === "applied") ? "✅"
|
|
337
|
-
: plan.actions.some(a => a.status === "failed") ? "❌" : "📋";
|
|
338
|
-
console.log(` ${icon} ${plan.nameHe}: ${plan.totalActions} actions (${plan.autoFixable} auto, ${plan.manualRequired} manual)`);
|
|
307
|
+
if (topFindings.length > 10) {
|
|
308
|
+
console.log(` ... and ${topFindings.length - 10} more. See full report.\n`);
|
|
339
309
|
}
|
|
310
|
+
console.log(" ──────────────────────────────────────");
|
|
311
|
+
console.log(" ⚠ Capsule provides recommendations only.");
|
|
312
|
+
console.log(" Fixes require understanding of your system —");
|
|
313
|
+
console.log(" tables, relationships, and business logic.");
|
|
314
|
+
console.log(" Work with your team to apply changes safely.");
|
|
340
315
|
console.log(" ══════════════════════════════════════\n");
|
|
341
|
-
//
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
(
|
|
345
|
-
log(ciMode, `Fix plan saved: ${plansPath}`);
|
|
346
|
-
// Write SQL migrations to files
|
|
347
|
-
for (const plan of capsuleResult.plans) {
|
|
348
|
-
for (const action of plan.actions) {
|
|
349
|
-
if (action.type === "file-create" && action.target.includes("migrations/")) {
|
|
350
|
-
const migPath = (0, path_1.resolve)(outputDir, action.target);
|
|
351
|
-
const migDir = (0, path_1.resolve)(outputDir, "migrations");
|
|
352
|
-
if (!(0, fs_1.existsSync)(migDir)) {
|
|
353
|
-
const { mkdirSync } = require("fs");
|
|
354
|
-
mkdirSync(migDir, { recursive: true });
|
|
355
|
-
}
|
|
356
|
-
(0, fs_1.writeFileSync)(migPath, action.content, "utf-8");
|
|
357
|
-
log(ciMode, `Migration: ${migPath}`);
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
// Send notifications if configured
|
|
364
|
-
if (config.notify && fixMode === "apply") {
|
|
365
|
-
const notifyPayload = {
|
|
366
|
-
event: capsuleResult.applied > 0 ? "fix-applied" : "scan-complete",
|
|
367
|
-
timestamp: new Date().toISOString(),
|
|
368
|
-
projectName: full.project_name || "unknown",
|
|
369
|
-
projectHash: full.proof_hash?.slice(0, 16) || "",
|
|
316
|
+
// Save recommendations to file
|
|
317
|
+
const recsPath = (0, path_1.resolve)(outputDir, "nodata-recommendations.json");
|
|
318
|
+
(0, fs_1.writeFileSync)(recsPath, JSON.stringify({
|
|
319
|
+
generated_at: new Date().toISOString(),
|
|
370
320
|
score: full.overall_score,
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
fixesApplied: capsuleResult.applied,
|
|
377
|
-
fixesFailed: capsuleResult.failed,
|
|
378
|
-
scanId: activation.scan_id,
|
|
379
|
-
proofHash: capsuleResult.proofHash,
|
|
380
|
-
};
|
|
381
|
-
await (0, registry_1.sendNotifications)(config, notifyPayload.event, notifyPayload, (msg) => log(ciMode, msg));
|
|
321
|
+
total_findings: topFindings.length,
|
|
322
|
+
disclaimer: "These are recommendations only. Capsule does not modify your code. Fixes require understanding of your system architecture, database schema, and business logic. Work with your development team to implement changes safely.",
|
|
323
|
+
recommendations: topFindings,
|
|
324
|
+
}, null, 2), "utf-8");
|
|
325
|
+
log(ciMode, `Recommendations: ${recsPath}`);
|
|
382
326
|
}
|
|
383
327
|
}
|
|
384
328
|
// ── CI mode: exit code ──
|
|
@@ -425,14 +369,16 @@ function loadOrCreateConfig(projectDir, overrides) {
|
|
|
425
369
|
}
|
|
426
370
|
function printHelp() {
|
|
427
371
|
console.log(`
|
|
428
|
-
NoData Guard v${VERSION} — Security Scanner +
|
|
372
|
+
NoData Guard v${VERSION} — Security Scanner + Recommendations
|
|
373
|
+
|
|
374
|
+
Scans your project locally for security issues and provides
|
|
375
|
+
actionable recommendations. Your code never leaves your machine.
|
|
376
|
+
Capsule does NOT modify your code — only you and your team can.
|
|
429
377
|
|
|
430
378
|
Usage:
|
|
431
|
-
npx nodata-guard --license-key NDC-XXXX
|
|
432
|
-
npx nodata-guard --license-key NDC-XXXX --
|
|
433
|
-
npx nodata-guard --license-key NDC-XXXX --
|
|
434
|
-
npx nodata-guard --license-key NDC-XXXX --schedule weekly # Setup CI schedule
|
|
435
|
-
npx nodata-guard --license-key NDC-XXXX --db $DATABASE_URL --fix # Full scan + fix
|
|
379
|
+
npx nodata-guard --license-key NDC-XXXX # Scan + recommend
|
|
380
|
+
npx nodata-guard --license-key NDC-XXXX --db $DATABASE_URL # Full scan (code + DB)
|
|
381
|
+
npx nodata-guard --license-key NDC-XXXX --schedule weekly # Setup CI schedule
|
|
436
382
|
|
|
437
383
|
Scan Options:
|
|
438
384
|
--license-key <key> NoData license key (or set NDC_LICENSE env var)
|
|
@@ -443,13 +389,6 @@ function printHelp() {
|
|
|
443
389
|
--fail-on <level> Exit 1 if issues at: critical | high | medium
|
|
444
390
|
--skip-send Don't send metadata to NoData
|
|
445
391
|
|
|
446
|
-
Capsule Options:
|
|
447
|
-
--fix-plan Generate fix plan (dry-run, no changes)
|
|
448
|
-
--fix Apply all auto-fixable remediation
|
|
449
|
-
--fix-only <fixers> Only run specific fixers (comma-separated)
|
|
450
|
-
Fixers: pii-encrypt, rls, secrets, routes-auth,
|
|
451
|
-
headers, csrf, rate-limit, gitignore
|
|
452
|
-
|
|
453
392
|
Schedule Options:
|
|
454
393
|
--schedule <preset> Install CI workflow: daily | weekly | monthly
|
|
455
394
|
--ci-provider <name> CI provider: github-actions | gitlab-ci | bitbucket | auto
|
|
@@ -458,28 +397,36 @@ function printHelp() {
|
|
|
458
397
|
Configure in .nodata-guard.json → notify: { email, webhook, slack, telegram }
|
|
459
398
|
|
|
460
399
|
Output files:
|
|
461
|
-
nodata-full-report.json
|
|
462
|
-
nodata-metadata-only.json
|
|
463
|
-
nodata-
|
|
464
|
-
migrations/*.sql Generated SQL migrations
|
|
400
|
+
nodata-full-report.json Full report — STAYS LOCAL
|
|
401
|
+
nodata-metadata-only.json Metadata only — sent to dashboard
|
|
402
|
+
nodata-recommendations.json Prioritized recommendations
|
|
465
403
|
|
|
466
|
-
What we
|
|
467
|
-
|
|
404
|
+
What we provide:
|
|
405
|
+
✓ Scan — find weak points (PII, routes, secrets, encryption)
|
|
406
|
+
✓ Recommend — prioritized actions with SOC control mapping
|
|
407
|
+
✓ Prove — cryptographic proof chain of scan results
|
|
408
|
+
✓ Monitor — track score over time via dashboard
|
|
409
|
+
|
|
410
|
+
What we NEVER do:
|
|
411
|
+
✗ Modify your code, database, or configuration
|
|
412
|
+
✗ Receive data values, source code, or credentials
|
|
413
|
+
|
|
414
|
+
Important:
|
|
415
|
+
Recommendations require understanding of YOUR system —
|
|
416
|
+
tables, relationships, business logic. Work with your team
|
|
417
|
+
to implement changes safely.
|
|
468
418
|
|
|
469
419
|
Examples:
|
|
470
|
-
#
|
|
420
|
+
# Scan and get recommendations
|
|
471
421
|
npx nodata-guard --license-key NDC-XXXX
|
|
472
422
|
|
|
473
|
-
# Full scan
|
|
474
|
-
npx nodata-guard --license-key NDC-XXXX --db $DATABASE_URL
|
|
475
|
-
|
|
476
|
-
# Only fix security headers and CSRF
|
|
477
|
-
npx nodata-guard --license-key NDC-XXXX --fix --fix-only headers,csrf
|
|
423
|
+
# Full scan with DB probe
|
|
424
|
+
npx nodata-guard --license-key NDC-XXXX --db $DATABASE_URL
|
|
478
425
|
|
|
479
426
|
# Setup weekly CI scan with GitHub Actions
|
|
480
427
|
npx nodata-guard --license-key NDC-XXXX --schedule weekly
|
|
481
428
|
|
|
482
|
-
# CI pipeline
|
|
429
|
+
# CI pipeline — fail on critical issues
|
|
483
430
|
npx nodata-guard --ci --fail-on critical
|
|
484
431
|
|
|
485
432
|
Documentation: https://nodatacapsule.com/guard
|
package/dist/reporter.js
CHANGED
|
@@ -123,7 +123,7 @@ function generateReports(input) {
|
|
|
123
123
|
critical: criticalSecrets,
|
|
124
124
|
high: highSecrets + plaintextPII,
|
|
125
125
|
medium: medSecrets,
|
|
126
|
-
|
|
126
|
+
recommendations_available: plaintextPII, // each plaintext field has a recommendation
|
|
127
127
|
},
|
|
128
128
|
// Fix suggestions — safe to send (just recommendation text, no code/values)
|
|
129
129
|
findings: [
|
|
@@ -203,7 +203,7 @@ function generateReports(input) {
|
|
|
203
203
|
critical_issues: criticalSecrets,
|
|
204
204
|
high_issues: highSecrets + plaintextPII,
|
|
205
205
|
medium_issues: medSecrets,
|
|
206
|
-
|
|
206
|
+
recommendations_available: plaintextPII,
|
|
207
207
|
},
|
|
208
208
|
proof_hash: proofHash,
|
|
209
209
|
metadata_preview: metadata,
|
package/dist/types.d.ts
CHANGED
|
@@ -84,7 +84,7 @@ export interface FullReport {
|
|
|
84
84
|
critical_issues: number;
|
|
85
85
|
high_issues: number;
|
|
86
86
|
medium_issues: number;
|
|
87
|
-
|
|
87
|
+
recommendations_available: number;
|
|
88
88
|
};
|
|
89
89
|
proof_hash: string;
|
|
90
90
|
metadata_preview: MetadataReport;
|
|
@@ -140,7 +140,7 @@ export interface MetadataReport {
|
|
|
140
140
|
critical: number;
|
|
141
141
|
high: number;
|
|
142
142
|
medium: number;
|
|
143
|
-
|
|
143
|
+
recommendations_available: number;
|
|
144
144
|
};
|
|
145
145
|
findings: Array<{
|
|
146
146
|
severity: "critical" | "high" | "medium" | "low";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodatachat/guard",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "NoData Guard — continuous security scanner. Runs locally, reports only metadata. Your data never leaves your machine.",
|
|
5
5
|
"main": "./dist/cli.js",
|
|
6
6
|
"types": "./dist/cli.d.ts",
|