@nodatachat/guard 2.0.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 +28 -0
- package/README.md +120 -0
- package/dist/activation.d.ts +8 -0
- package/dist/activation.js +110 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +458 -0
- package/dist/code-scanner.d.ts +14 -0
- package/dist/code-scanner.js +309 -0
- package/dist/db-scanner.d.ts +7 -0
- package/dist/db-scanner.js +185 -0
- package/dist/fixers/fix-csrf.d.ts +9 -0
- package/dist/fixers/fix-csrf.js +113 -0
- package/dist/fixers/fix-gitignore.d.ts +9 -0
- package/dist/fixers/fix-gitignore.js +71 -0
- package/dist/fixers/fix-headers.d.ts +9 -0
- package/dist/fixers/fix-headers.js +118 -0
- package/dist/fixers/fix-pii-encrypt.d.ts +9 -0
- package/dist/fixers/fix-pii-encrypt.js +298 -0
- package/dist/fixers/fix-rate-limit.d.ts +9 -0
- package/dist/fixers/fix-rate-limit.js +102 -0
- package/dist/fixers/fix-rls.d.ts +9 -0
- package/dist/fixers/fix-rls.js +243 -0
- package/dist/fixers/fix-routes-auth.d.ts +9 -0
- package/dist/fixers/fix-routes-auth.js +82 -0
- package/dist/fixers/fix-secrets.d.ts +9 -0
- package/dist/fixers/fix-secrets.js +132 -0
- package/dist/fixers/index.d.ts +11 -0
- package/dist/fixers/index.js +37 -0
- package/dist/fixers/registry.d.ts +25 -0
- package/dist/fixers/registry.js +249 -0
- package/dist/fixers/scheduler.d.ts +9 -0
- package/dist/fixers/scheduler.js +254 -0
- package/dist/fixers/types.d.ts +160 -0
- package/dist/fixers/types.js +11 -0
- package/dist/reporter.d.ts +28 -0
- package/dist/reporter.js +185 -0
- package/dist/types.d.ts +154 -0
- package/dist/types.js +5 -0
- package/package.json +61 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# NoData Guard License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 NoDataChat Ltd. All rights reserved.
|
|
4
|
+
|
|
5
|
+
## Terms
|
|
6
|
+
|
|
7
|
+
This software is proprietary. You may use it under the terms of your NoDataChat subscription agreement.
|
|
8
|
+
|
|
9
|
+
### Permitted Uses
|
|
10
|
+
- Running scans on your own projects with a valid license key
|
|
11
|
+
- Integrating into your CI/CD pipelines
|
|
12
|
+
- Generating reports for internal use
|
|
13
|
+
|
|
14
|
+
### Prohibited Uses
|
|
15
|
+
- Redistributing or reselling the software
|
|
16
|
+
- Reverse engineering or decompiling
|
|
17
|
+
- Removing license key verification
|
|
18
|
+
- Using the software to scan third-party projects without authorization
|
|
19
|
+
|
|
20
|
+
### Data Privacy
|
|
21
|
+
- Guard runs locally on your machine
|
|
22
|
+
- Source code is never uploaded to NoDataChat servers
|
|
23
|
+
- Only metadata reports (table names, counts, scores) are transmitted
|
|
24
|
+
- You can opt out of metadata transmission with --skip-send
|
|
25
|
+
|
|
26
|
+
For the full license agreement, visit: https://nodatachat.com/legal/guard-license
|
|
27
|
+
|
|
28
|
+
Contact: legal@nodatachat.com
|
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# @nodatachat/guard
|
|
2
|
+
|
|
3
|
+
**NoData Guard** — Continuous security scanner that runs locally. Your data never leaves your machine.
|
|
4
|
+
|
|
5
|
+
Guard scans your codebase and (optionally) your database for security issues: exposed PII fields, missing encryption, unprotected routes, hardcoded secrets, and known CVEs. It generates two reports:
|
|
6
|
+
|
|
7
|
+
- **`nodata-full-report.json`** — Full details, stays local on your machine
|
|
8
|
+
- **`nodata-metadata-only.json`** — Metadata only (table names, counts, scores), sent to NoData for dashboard tracking
|
|
9
|
+
|
|
10
|
+
**You can diff the two files to verify no data values were sent.**
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Run directly (no install needed)
|
|
16
|
+
npx nodata-guard --license-key NDC-XXXX-XXXX-XXXX
|
|
17
|
+
|
|
18
|
+
# With database scan (Business Pro+)
|
|
19
|
+
npx nodata-guard --license-key NDC-XXXX --db postgres://user:pass@host/db
|
|
20
|
+
|
|
21
|
+
# CI/CD mode — fail on critical findings
|
|
22
|
+
npx nodata-guard --license-key $NDC_LICENSE --ci --fail-on critical
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
| Feature | Free | Business | Business Pro | Enterprise |
|
|
28
|
+
|---------|------|----------|-------------|------------|
|
|
29
|
+
| Code scan (PII, routes, secrets) | - | Yes | Yes | Yes |
|
|
30
|
+
| Seed test (proof capsule) | - | Yes | Yes | Yes |
|
|
31
|
+
| Continuous scanning | - | Yes | Yes | Yes |
|
|
32
|
+
| Dashboard (scan history) | - | Yes | Yes | Yes |
|
|
33
|
+
| Database scan (DB Probe) | - | - | Yes | Yes |
|
|
34
|
+
| CI/CD integration | - | - | Yes | Yes |
|
|
35
|
+
| Proof certificate | - | - | Yes | Yes |
|
|
36
|
+
| On-prem deployment | - | - | - | Yes |
|
|
37
|
+
| White-label | - | - | - | Yes |
|
|
38
|
+
|
|
39
|
+
## Options
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
--license-key KEY License key (or set NDC_LICENSE env var)
|
|
43
|
+
--db URL Database connection string (or set DATABASE_URL)
|
|
44
|
+
--dir PATH Project directory to scan (default: cwd)
|
|
45
|
+
--output PATH Output directory for reports (default: cwd)
|
|
46
|
+
--ci CI mode — minimal output, exit codes
|
|
47
|
+
--fail-on LEVEL Exit 1 on issues at this level: critical, high, medium
|
|
48
|
+
--skip-send Don't send metadata report to NoData
|
|
49
|
+
--version Show version
|
|
50
|
+
--help Show help
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## What Gets Scanned
|
|
54
|
+
|
|
55
|
+
**Code Scanner (7 checks):**
|
|
56
|
+
- PII field detection (24 categories: email, phone, SSN, credit card, etc.)
|
|
57
|
+
- Encryption coverage (are PII fields encrypted?)
|
|
58
|
+
- Route auth detection (42+ auth patterns)
|
|
59
|
+
- Stack detection (framework, database, hosting)
|
|
60
|
+
- Secret scanning (26 patterns, Gitleaks-style)
|
|
61
|
+
- Dependency vulnerability checks
|
|
62
|
+
- CVE detection (20 known vulnerabilities)
|
|
63
|
+
|
|
64
|
+
**Database Scanner (6 checks):**
|
|
65
|
+
- Schema introspection (table/column inventory)
|
|
66
|
+
- PII column detection
|
|
67
|
+
- Encryption verification (LEFT(value,13) only — never reads full values)
|
|
68
|
+
- RLS policy coverage
|
|
69
|
+
- Access control audit
|
|
70
|
+
- Infrastructure checks (SSL, timeouts)
|
|
71
|
+
|
|
72
|
+
## Privacy Guarantee
|
|
73
|
+
|
|
74
|
+
- Guard runs **entirely on your machine**
|
|
75
|
+
- Source code is **never uploaded**
|
|
76
|
+
- Database values are **never read** (only schema metadata)
|
|
77
|
+
- The metadata report contains only: table names, column counts, boolean flags, scores
|
|
78
|
+
- You can verify this by diffing `nodata-full-report.json` vs `nodata-metadata-only.json`
|
|
79
|
+
|
|
80
|
+
## Dashboard
|
|
81
|
+
|
|
82
|
+
After running Guard, log in at [nodatachat.com/guard](https://nodatachat.com/guard) with your license key to see:
|
|
83
|
+
|
|
84
|
+
- Score trends over time
|
|
85
|
+
- Scan history with comparison
|
|
86
|
+
- Issue breakdown by severity
|
|
87
|
+
- Encryption coverage progress
|
|
88
|
+
- Database security posture
|
|
89
|
+
|
|
90
|
+
## CI/CD Integration
|
|
91
|
+
|
|
92
|
+
### GitHub Actions
|
|
93
|
+
|
|
94
|
+
```yaml
|
|
95
|
+
- name: NoData Guard Security Scan
|
|
96
|
+
run: npx nodata-guard --license-key ${{ secrets.NDC_LICENSE }} --ci --fail-on critical
|
|
97
|
+
env:
|
|
98
|
+
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### GitLab CI
|
|
102
|
+
|
|
103
|
+
```yaml
|
|
104
|
+
security-scan:
|
|
105
|
+
script:
|
|
106
|
+
- npx nodata-guard --license-key $NDC_LICENSE --ci --fail-on critical
|
|
107
|
+
variables:
|
|
108
|
+
DATABASE_URL: $DATABASE_URL
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## License
|
|
112
|
+
|
|
113
|
+
Proprietary — see [LICENSE.md](LICENSE.md)
|
|
114
|
+
|
|
115
|
+
## Links
|
|
116
|
+
|
|
117
|
+
- [Website](https://nodatachat.com)
|
|
118
|
+
- [Guard Dashboard](https://nodatachat.com/guard)
|
|
119
|
+
- [Getting Started](https://nodatachat.com/guard/onboarding)
|
|
120
|
+
- [Pricing](https://nodatachat.com/pricing)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ActivationResponse } from "./types";
|
|
2
|
+
export declare function computeProjectHash(projectDir: string): string;
|
|
3
|
+
export declare function activate(options: {
|
|
4
|
+
licenseKey: string;
|
|
5
|
+
projectDir: string;
|
|
6
|
+
scanType: "code" | "db" | "full";
|
|
7
|
+
apiBase?: string;
|
|
8
|
+
}): Promise<ActivationResponse>;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ═══════════════════════════════════════════════════════════
|
|
3
|
+
// @nodatachat/guard — License Activation
|
|
4
|
+
//
|
|
5
|
+
// Contacts NoData API to verify license and get activation key.
|
|
6
|
+
// Without activation key, the scanner cannot run.
|
|
7
|
+
//
|
|
8
|
+
// Flow:
|
|
9
|
+
// 1. Guard sends: license_key + project_hash (no code, no data)
|
|
10
|
+
// 2. API checks: license valid? tier? features?
|
|
11
|
+
// 3. API returns: activation_key (one-time, TTL 5 min)
|
|
12
|
+
// 4. Guard uses activation_key to unlock scanner + encrypt report
|
|
13
|
+
// ═══════════════════════════════════════════════════════════
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.computeProjectHash = computeProjectHash;
|
|
16
|
+
exports.activate = activate;
|
|
17
|
+
const crypto_1 = require("crypto");
|
|
18
|
+
const fs_1 = require("fs");
|
|
19
|
+
const path_1 = require("path");
|
|
20
|
+
const GUARD_VERSION = "2.0.0";
|
|
21
|
+
const API_BASE = process.env.GUARD_API_BASE || "https://nodatachat.com/api/guard";
|
|
22
|
+
// Dev license keys that work without server (for development and demos)
|
|
23
|
+
const DEV_LICENSES = new Set(["NDC-DEV", "NDC-DEMO", "NDC-TEST"]);
|
|
24
|
+
// ── Project fingerprint (directory structure only, no file contents) ──
|
|
25
|
+
function computeProjectHash(projectDir) {
|
|
26
|
+
const paths = [];
|
|
27
|
+
function walk(dir, depth) {
|
|
28
|
+
if (depth > 5)
|
|
29
|
+
return; // max depth for fingerprint
|
|
30
|
+
try {
|
|
31
|
+
const entries = (0, fs_1.readdirSync)(dir, { withFileTypes: true });
|
|
32
|
+
for (const entry of entries) {
|
|
33
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist")
|
|
34
|
+
continue;
|
|
35
|
+
const fullPath = (0, path_1.join)(dir, entry.name);
|
|
36
|
+
const relativePath = fullPath.replace(projectDir, "");
|
|
37
|
+
if (entry.isDirectory()) {
|
|
38
|
+
paths.push(`d:${relativePath}`);
|
|
39
|
+
walk(fullPath, depth + 1);
|
|
40
|
+
}
|
|
41
|
+
else if (entry.isFile()) {
|
|
42
|
+
try {
|
|
43
|
+
const stat = (0, fs_1.statSync)(fullPath);
|
|
44
|
+
paths.push(`f:${relativePath}:${stat.size}`);
|
|
45
|
+
}
|
|
46
|
+
catch { /* skip */ }
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch { /* skip */ }
|
|
51
|
+
}
|
|
52
|
+
walk(projectDir, 0);
|
|
53
|
+
paths.sort();
|
|
54
|
+
return (0, crypto_1.createHash)("sha256").update(paths.join("|")).digest("hex");
|
|
55
|
+
}
|
|
56
|
+
// ── Activate license ──
|
|
57
|
+
async function activate(options) {
|
|
58
|
+
const { licenseKey, projectDir, scanType, apiBase = API_BASE } = options;
|
|
59
|
+
const projectHash = computeProjectHash(projectDir);
|
|
60
|
+
// Dev mode — skip server activation for development/demo licenses
|
|
61
|
+
if (DEV_LICENSES.has(licenseKey)) {
|
|
62
|
+
return {
|
|
63
|
+
success: true,
|
|
64
|
+
activation_key: `dev-${Date.now()}`,
|
|
65
|
+
tier: licenseKey === "NDC-DEV" ? "enterprise" : "business",
|
|
66
|
+
features: ["code-scan", "db-probe", "fix-plan", "fix-apply", "schedule", "notify"],
|
|
67
|
+
scan_id: `scan-dev-${Date.now().toString(36)}`,
|
|
68
|
+
expires_at: new Date(Date.now() + 3600000).toISOString(),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const request = {
|
|
72
|
+
license_key: licenseKey,
|
|
73
|
+
project_hash: projectHash,
|
|
74
|
+
guard_version: GUARD_VERSION,
|
|
75
|
+
scan_type: scanType,
|
|
76
|
+
};
|
|
77
|
+
try {
|
|
78
|
+
const res = await fetch(`${apiBase}/activate`, {
|
|
79
|
+
method: "POST",
|
|
80
|
+
headers: { "Content-Type": "application/json" },
|
|
81
|
+
body: JSON.stringify(request),
|
|
82
|
+
signal: AbortSignal.timeout(10000),
|
|
83
|
+
});
|
|
84
|
+
if (!res.ok) {
|
|
85
|
+
const text = await res.text();
|
|
86
|
+
return {
|
|
87
|
+
success: false,
|
|
88
|
+
activation_key: "",
|
|
89
|
+
tier: "",
|
|
90
|
+
features: [],
|
|
91
|
+
scan_id: "",
|
|
92
|
+
expires_at: "",
|
|
93
|
+
error: `Activation failed (${res.status}): ${text}`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return res.json();
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
// Network error — allow offline scanning with limited features
|
|
100
|
+
return {
|
|
101
|
+
success: true,
|
|
102
|
+
activation_key: `offline-${Date.now()}`,
|
|
103
|
+
tier: "free",
|
|
104
|
+
features: ["code-scan"],
|
|
105
|
+
scan_id: `scan-offline-${Date.now().toString(36)}`,
|
|
106
|
+
expires_at: new Date(Date.now() + 3600000).toISOString(),
|
|
107
|
+
error: `Server unreachable — running in offline mode (code-scan only)`,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
package/dist/cli.d.ts
ADDED