@nodatachat/guard 2.0.0 → 2.1.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/LICENSE.md +5 -5
- package/README.md +5 -5
- package/dist/activation.js +1 -1
- package/dist/cli.js +38 -5
- package/dist/fixers/registry.js +1 -1
- package/dist/reporter.js +27 -0
- package/dist/types.d.ts +8 -0
- package/package.json +3 -3
package/LICENSE.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# NoData Guard License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2026
|
|
3
|
+
Copyright (c) 2026 Capsule Ltd. All rights reserved.
|
|
4
4
|
|
|
5
5
|
## Terms
|
|
6
6
|
|
|
7
|
-
This software is proprietary. You may use it under the terms of your
|
|
7
|
+
This software is proprietary. You may use it under the terms of your Capsule subscription agreement.
|
|
8
8
|
|
|
9
9
|
### Permitted Uses
|
|
10
10
|
- Running scans on your own projects with a valid license key
|
|
@@ -19,10 +19,10 @@ This software is proprietary. You may use it under the terms of your NoDataChat
|
|
|
19
19
|
|
|
20
20
|
### Data Privacy
|
|
21
21
|
- Guard runs locally on your machine
|
|
22
|
-
- Source code is never uploaded to
|
|
22
|
+
- Source code is never uploaded to Capsule servers
|
|
23
23
|
- Only metadata reports (table names, counts, scores) are transmitted
|
|
24
24
|
- You can opt out of metadata transmission with --skip-send
|
|
25
25
|
|
|
26
|
-
For the full license agreement, visit: https://
|
|
26
|
+
For the full license agreement, visit: https://nodatacapsule.com/legal/guard-license
|
|
27
27
|
|
|
28
|
-
Contact: legal@
|
|
28
|
+
Contact: legal@nodatacapsule.com
|
package/README.md
CHANGED
|
@@ -79,7 +79,7 @@ npx nodata-guard --license-key $NDC_LICENSE --ci --fail-on critical
|
|
|
79
79
|
|
|
80
80
|
## Dashboard
|
|
81
81
|
|
|
82
|
-
After running Guard, log in at [
|
|
82
|
+
After running Guard, log in at [nodatacapsule.com/guard](https://nodatacapsule.com/guard) with your license key to see:
|
|
83
83
|
|
|
84
84
|
- Score trends over time
|
|
85
85
|
- Scan history with comparison
|
|
@@ -114,7 +114,7 @@ Proprietary — see [LICENSE.md](LICENSE.md)
|
|
|
114
114
|
|
|
115
115
|
## Links
|
|
116
116
|
|
|
117
|
-
- [Website](https://
|
|
118
|
-
- [Guard Dashboard](https://
|
|
119
|
-
- [Getting Started](https://
|
|
120
|
-
- [Pricing](https://
|
|
117
|
+
- [Website](https://nodatacapsule.com)
|
|
118
|
+
- [Guard Dashboard](https://nodatacapsule.com/guard)
|
|
119
|
+
- [Getting Started](https://nodatacapsule.com/guard/onboarding)
|
|
120
|
+
- [Pricing](https://nodatacapsule.com/pricing)
|
package/dist/activation.js
CHANGED
|
@@ -18,7 +18,7 @@ const crypto_1 = require("crypto");
|
|
|
18
18
|
const fs_1 = require("fs");
|
|
19
19
|
const path_1 = require("path");
|
|
20
20
|
const GUARD_VERSION = "2.0.0";
|
|
21
|
-
const API_BASE = process.env.GUARD_API_BASE || "https://
|
|
21
|
+
const API_BASE = process.env.GUARD_API_BASE || "https://nodatacapsule.com/api/guard";
|
|
22
22
|
// Dev license keys that work without server (for development and demos)
|
|
23
23
|
const DEV_LICENSES = new Set(["NDC-DEV", "NDC-DEMO", "NDC-TEST"]);
|
|
24
24
|
// ── Project fingerprint (directory structure only, no file contents) ──
|
package/dist/cli.js
CHANGED
|
@@ -87,12 +87,44 @@ async function main() {
|
|
|
87
87
|
}
|
|
88
88
|
// Env fallbacks
|
|
89
89
|
if (!licenseKey)
|
|
90
|
-
licenseKey = process.env.NDC_LICENSE || process.env.NODATA_LICENSE_KEY;
|
|
90
|
+
licenseKey = process.env.NDC_LICENSE || process.env.NODATA_LICENSE_KEY || process.env.NODATA_API_KEY || process.env.NDC_API_KEY;
|
|
91
91
|
if (!dbUrl)
|
|
92
92
|
dbUrl = process.env.DATABASE_URL;
|
|
93
|
+
// Shared Protect config fallback (~/.nodata/config.json)
|
|
93
94
|
if (!licenseKey) {
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
try {
|
|
96
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
97
|
+
const configPath = require("path").join(home, ".nodata", "config.json");
|
|
98
|
+
if (require("fs").existsSync(configPath)) {
|
|
99
|
+
const config = JSON.parse(require("fs").readFileSync(configPath, "utf-8"));
|
|
100
|
+
if (config.api_key) {
|
|
101
|
+
licenseKey = config.api_key;
|
|
102
|
+
console.log(`\n \x1b[32m✓\x1b[0m Using API key from NoData Protect (~/.nodata/config.json)\n`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch { /* ignore */ }
|
|
107
|
+
}
|
|
108
|
+
// Capsule config fallback (.capsule.json)
|
|
109
|
+
if (!licenseKey) {
|
|
110
|
+
try {
|
|
111
|
+
const capsulePath = require("path").join(projectDir, ".capsule.json");
|
|
112
|
+
if (require("fs").existsSync(capsulePath)) {
|
|
113
|
+
const config = JSON.parse(require("fs").readFileSync(capsulePath, "utf-8"));
|
|
114
|
+
if (config.licenseKey) {
|
|
115
|
+
licenseKey = config.licenseKey;
|
|
116
|
+
console.log(`\n \x1b[32m✓\x1b[0m Using API key from Capsule config (.capsule.json)\n`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch { /* ignore */ }
|
|
121
|
+
}
|
|
122
|
+
if (!licenseKey) {
|
|
123
|
+
console.error("\n \x1b[31m✗\x1b[0m No API key found.\n");
|
|
124
|
+
console.error(" Options:");
|
|
125
|
+
console.error(" 1. Run \x1b[36mnpx @nodatachat/protect init\x1b[0m first (creates key automatically)");
|
|
126
|
+
console.error(" 2. Pass \x1b[36m--license-key YOUR_KEY\x1b[0m");
|
|
127
|
+
console.error(" 3. Set \x1b[36mNDC_LICENSE=YOUR_KEY\x1b[0m in environment\n");
|
|
96
128
|
process.exit(1);
|
|
97
129
|
}
|
|
98
130
|
// ── Schedule setup (no scan needed) ──
|
|
@@ -204,12 +236,13 @@ async function main() {
|
|
|
204
236
|
if (!skipSend) {
|
|
205
237
|
log(ciMode, "Sending metadata to NoData...");
|
|
206
238
|
try {
|
|
207
|
-
const res = await fetch("https://
|
|
239
|
+
const res = await fetch("https://nodatacapsule.com/api/guard/report", {
|
|
208
240
|
method: "POST",
|
|
209
241
|
headers: {
|
|
210
242
|
"Content-Type": "application/json",
|
|
211
243
|
"X-Scan-Id": activation.scan_id,
|
|
212
244
|
"X-Activation-Key": activation.activation_key,
|
|
245
|
+
"X-License-Key": licenseKey || "",
|
|
213
246
|
},
|
|
214
247
|
body: JSON.stringify(metadata),
|
|
215
248
|
signal: AbortSignal.timeout(10000),
|
|
@@ -449,7 +482,7 @@ function printHelp() {
|
|
|
449
482
|
# CI pipeline
|
|
450
483
|
npx nodata-guard --ci --fail-on critical
|
|
451
484
|
|
|
452
|
-
Documentation: https://
|
|
485
|
+
Documentation: https://nodatacapsule.com/guard
|
|
453
486
|
`);
|
|
454
487
|
}
|
|
455
488
|
main().catch((err) => {
|
package/dist/fixers/registry.js
CHANGED
|
@@ -156,7 +156,7 @@ async function sendNotifications(config, event, payload, onLog) {
|
|
|
156
156
|
if (config.notify.email?.length) {
|
|
157
157
|
for (const email of config.notify.email) {
|
|
158
158
|
try {
|
|
159
|
-
await fetch("https://
|
|
159
|
+
await fetch("https://nodatacapsule.com/api/guard/notify", {
|
|
160
160
|
method: "POST",
|
|
161
161
|
headers: { "Content-Type": "application/json" },
|
|
162
162
|
body: JSON.stringify({ channel: "email", to: email, payload }),
|
package/dist/reporter.js
CHANGED
|
@@ -125,6 +125,33 @@ function generateReports(input) {
|
|
|
125
125
|
medium: medSecrets,
|
|
126
126
|
fixes_available: plaintextPII, // each plaintext field has a migration fix
|
|
127
127
|
},
|
|
128
|
+
// Fix suggestions — safe to send (just recommendation text, no code/values)
|
|
129
|
+
findings: [
|
|
130
|
+
...allPII.filter(f => !f.encrypted).map(f => ({
|
|
131
|
+
severity: "high",
|
|
132
|
+
category: "pii",
|
|
133
|
+
rule_id: `PII_${f.pii_type.toUpperCase()}`,
|
|
134
|
+
title: `${f.table}.${f.column} — ${f.pii_type} stored in plaintext`,
|
|
135
|
+
fix_suggestion: `Add AES-256-GCM encryption to ${f.table}.${f.column} via Capsule field permissions`,
|
|
136
|
+
soc_control: "CC6.7",
|
|
137
|
+
})),
|
|
138
|
+
...(input.code?.secrets.filter(s => !s.is_env_interpolated) || []).map(s => ({
|
|
139
|
+
severity: s.severity,
|
|
140
|
+
category: "secrets",
|
|
141
|
+
rule_id: `SECRET_${s.type.toUpperCase().replace(/-/g, "_")}`,
|
|
142
|
+
title: `Hardcoded ${s.type} in ${s.file}:${s.line}`,
|
|
143
|
+
fix_suggestion: `Move to .env and encrypt with @nodatachat/protect`,
|
|
144
|
+
soc_control: "CC6.1",
|
|
145
|
+
})),
|
|
146
|
+
...(input.code?.routes.filter(r => !r.has_auth) || []).slice(0, 20).map(r => ({
|
|
147
|
+
severity: "high",
|
|
148
|
+
category: "auth",
|
|
149
|
+
rule_id: "ROUTE_NO_AUTH",
|
|
150
|
+
title: `Unprotected route: ${r.path}`,
|
|
151
|
+
fix_suggestion: `Add authentication middleware (withAuth or API key check)`,
|
|
152
|
+
soc_control: "CC6.3",
|
|
153
|
+
})),
|
|
154
|
+
],
|
|
128
155
|
proof_hash: proofHash,
|
|
129
156
|
privacy: {
|
|
130
157
|
contains_data_values: false,
|
package/dist/types.d.ts
CHANGED
|
@@ -142,6 +142,14 @@ export interface MetadataReport {
|
|
|
142
142
|
medium: number;
|
|
143
143
|
fixes_available: number;
|
|
144
144
|
};
|
|
145
|
+
findings: Array<{
|
|
146
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
147
|
+
category: string;
|
|
148
|
+
rule_id: string;
|
|
149
|
+
title: string;
|
|
150
|
+
fix_suggestion: string;
|
|
151
|
+
soc_control: string;
|
|
152
|
+
}>;
|
|
145
153
|
proof_hash: string;
|
|
146
154
|
privacy: {
|
|
147
155
|
contains_data_values: false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodatachat/guard",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.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",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"devsecops"
|
|
50
50
|
],
|
|
51
51
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
52
|
-
"homepage": "https://
|
|
52
|
+
"homepage": "https://nodatacapsule.com/guard",
|
|
53
53
|
"repository": {
|
|
54
54
|
"type": "git",
|
|
55
55
|
"url": "https://github.com/nodatachat/guard"
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"bugs": {
|
|
58
58
|
"url": "https://github.com/nodatachat/guard/issues"
|
|
59
59
|
},
|
|
60
|
-
"author": "
|
|
60
|
+
"author": "Capsule <support@nodatacapsule.com>"
|
|
61
61
|
}
|