@nodatachat/guard 2.5.1 → 2.6.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 +1 -1
- package/dist/db-scanner.js +21 -6
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -26,7 +26,7 @@ const reporter_1 = require("./reporter");
|
|
|
26
26
|
const scheduler_1 = require("./fixers/scheduler");
|
|
27
27
|
const vault_crypto_1 = require("./vault-crypto");
|
|
28
28
|
const capsule_dir_1 = require("./capsule-dir");
|
|
29
|
-
const VERSION = "2.
|
|
29
|
+
const VERSION = "2.6.0";
|
|
30
30
|
async function main() {
|
|
31
31
|
const args = process.argv.slice(2);
|
|
32
32
|
// ── Subcommand routing ──
|
package/dist/db-scanner.js
CHANGED
|
@@ -109,30 +109,38 @@ async function scanDatabase(connectionString, onProgress) {
|
|
|
109
109
|
// aes256gcm:v1: — legacy direct encryption (13 chars)
|
|
110
110
|
// enc:v1: — Capsule Proxy encryption (7 chars)
|
|
111
111
|
// ndc_enc_ — @nodatachat/protect format (8 chars)
|
|
112
|
+
// enc: — any enc: prefix variant (4 chars)
|
|
113
|
+
// Also checks for long base64 strings (>80 chars, alphanumeric)
|
|
112
114
|
const { rows } = await client.query(`
|
|
113
115
|
SELECT
|
|
114
116
|
count(*) as total,
|
|
115
117
|
count(${quoteIdent(col)}) as non_null,
|
|
116
118
|
count(*) FILTER (WHERE LEFT(${quoteIdent(col)}::text, 13) = 'aes256gcm:v1:') as aes_gcm,
|
|
117
119
|
count(*) FILTER (WHERE LEFT(${quoteIdent(col)}::text, 7) = 'enc:v1:') as enc_v1,
|
|
120
|
+
count(*) FILTER (WHERE LEFT(${quoteIdent(col)}::text, 4) = 'enc:') as enc_any,
|
|
118
121
|
count(*) FILTER (WHERE LEFT(${quoteIdent(col)}::text, 8) = 'ndc_enc_') as ndc_enc,
|
|
119
122
|
count(*) FILTER (WHERE LENGTH(${quoteIdent(col)}::text) > 80
|
|
120
|
-
AND ${quoteIdent(col)}::text ~ '^[A-Za-z0-9
|
|
123
|
+
AND ${quoteIdent(col)}::text ~ '^[A-Za-z0-9+/=:_-]+$') as base64_long
|
|
121
124
|
FROM ${quoteIdent(field.table)}
|
|
122
125
|
`);
|
|
123
126
|
const total = parseInt(rows[0].total);
|
|
124
127
|
const nonNull = parseInt(rows[0].non_null);
|
|
125
128
|
const aesGcm = parseInt(rows[0].aes_gcm);
|
|
126
129
|
const encV1 = parseInt(rows[0].enc_v1);
|
|
130
|
+
const encAny = parseInt(rows[0].enc_any);
|
|
127
131
|
const ndcEnc = parseInt(rows[0].ndc_enc);
|
|
128
132
|
const b64 = parseInt(rows[0].base64_long);
|
|
129
|
-
|
|
133
|
+
// enc_any catches enc:v1:, enc:v2:, enc:aes:, etc.
|
|
134
|
+
// Use the most specific match for naming, but count all enc: variants
|
|
135
|
+
const encDirectPrefixes = Math.max(aesGcm, encV1, encAny, ndcEnc);
|
|
136
|
+
const encCount = encDirectPrefixes + (encDirectPrefixes === 0 ? b64 : 0);
|
|
130
137
|
// Determine pattern name for reporting
|
|
131
138
|
const pattern = aesGcm > 0 ? "aes256gcm:v1"
|
|
132
139
|
: encV1 > 0 ? "enc:v1 (Capsule Proxy)"
|
|
133
|
-
:
|
|
134
|
-
:
|
|
135
|
-
: "
|
|
140
|
+
: encAny > 0 ? "enc: (encrypted prefix)"
|
|
141
|
+
: ndcEnc > 0 ? "ndc_enc (Protect)"
|
|
142
|
+
: b64 > 0 ? "base64_long"
|
|
143
|
+
: "unknown";
|
|
136
144
|
if (isCompanion && encCount > 0) {
|
|
137
145
|
field.encrypted = true;
|
|
138
146
|
field.encryption_pattern = pattern;
|
|
@@ -140,10 +148,17 @@ async function scanDatabase(connectionString, onProgress) {
|
|
|
140
148
|
}
|
|
141
149
|
else if (!isCompanion) {
|
|
142
150
|
field.row_count = total;
|
|
143
|
-
|
|
151
|
+
// Mark as encrypted if:
|
|
152
|
+
// - At least 1 row has an encryption prefix, AND
|
|
153
|
+
// - At least 30% of non-null rows are encrypted (threshold for partial encryption)
|
|
154
|
+
// OR at least 1 row has encryption AND total rows < 10 (small table — any encryption counts)
|
|
155
|
+
const threshold = nonNull > 0 ? encCount / nonNull : 0;
|
|
156
|
+
if (encCount > 0 && (threshold >= 0.3 || (nonNull < 10 && encCount > 0))) {
|
|
144
157
|
field.encrypted = true;
|
|
145
158
|
field.encryption_pattern = pattern;
|
|
146
159
|
field.encrypted_count = encCount;
|
|
160
|
+
// Also record the sentinel prefix for proof.json
|
|
161
|
+
field.sentinel_prefix = pattern;
|
|
147
162
|
}
|
|
148
163
|
}
|
|
149
164
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodatachat/guard",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.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",
|