@monoes/monomindcli 2.11.8 → 2.11.10

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 (121) hide show
  1. package/README.md +1 -1
  2. package/bin/cli.js +17 -8
  3. package/dist/src/commands/crash-reporting.d.ts +3 -1
  4. package/dist/src/commands/crash-reporting.d.ts.map +1 -1
  5. package/dist/src/commands/crash-reporting.js +26 -10
  6. package/dist/src/commands/crash-reporting.js.map +1 -1
  7. package/dist/src/commands/doctor-env-checks.d.ts +9 -0
  8. package/dist/src/commands/doctor-env-checks.d.ts.map +1 -1
  9. package/dist/src/commands/doctor-env-checks.js +31 -0
  10. package/dist/src/commands/doctor-env-checks.js.map +1 -1
  11. package/dist/src/commands/doctor-monoes-checks.d.ts +12 -0
  12. package/dist/src/commands/doctor-monoes-checks.d.ts.map +1 -1
  13. package/dist/src/commands/doctor-monoes-checks.js +142 -1
  14. package/dist/src/commands/doctor-monoes-checks.js.map +1 -1
  15. package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
  16. package/dist/src/commands/doctor-project-checks.js +8 -3
  17. package/dist/src/commands/doctor-project-checks.js.map +1 -1
  18. package/dist/src/commands/doctor.d.ts.map +1 -1
  19. package/dist/src/commands/doctor.js +11 -3
  20. package/dist/src/commands/doctor.js.map +1 -1
  21. package/dist/src/commands/mcp.d.ts.map +1 -1
  22. package/dist/src/commands/mcp.js +16 -0
  23. package/dist/src/commands/mcp.js.map +1 -1
  24. package/dist/src/commands/org-observe.d.ts.map +1 -1
  25. package/dist/src/commands/org-observe.js +29 -4
  26. package/dist/src/commands/org-observe.js.map +1 -1
  27. package/dist/src/commands/org.d.ts.map +1 -1
  28. package/dist/src/commands/org.js +12 -3
  29. package/dist/src/commands/org.js.map +1 -1
  30. package/dist/src/init/executor.d.ts.map +1 -1
  31. package/dist/src/init/executor.js +17 -0
  32. package/dist/src/init/executor.js.map +1 -1
  33. package/dist/src/init/mcp-generator.d.ts +2 -7
  34. package/dist/src/init/mcp-generator.d.ts.map +1 -1
  35. package/dist/src/init/mcp-generator.js +15 -17
  36. package/dist/src/init/mcp-generator.js.map +1 -1
  37. package/dist/src/init/write-claude.d.ts.map +1 -1
  38. package/dist/src/init/write-claude.js +9 -0
  39. package/dist/src/init/write-claude.js.map +1 -1
  40. package/dist/src/init/write-runtime-config.d.ts +8 -0
  41. package/dist/src/init/write-runtime-config.d.ts.map +1 -1
  42. package/dist/src/init/write-runtime-config.js +69 -14
  43. package/dist/src/init/write-runtime-config.js.map +1 -1
  44. package/dist/src/mcp/monoes-mcp-entry.mjs +152 -0
  45. package/dist/src/mcp/monoes-proxy.d.ts +48 -0
  46. package/dist/src/mcp/monoes-proxy.d.ts.map +1 -0
  47. package/dist/src/mcp/monoes-proxy.js +240 -0
  48. package/dist/src/mcp/monoes-proxy.js.map +1 -0
  49. package/dist/src/memory/embedding-operations.d.ts.map +1 -1
  50. package/dist/src/memory/embedding-operations.js +5 -0
  51. package/dist/src/memory/embedding-operations.js.map +1 -1
  52. package/dist/src/orgrt/completion-gate.d.ts +58 -0
  53. package/dist/src/orgrt/completion-gate.d.ts.map +1 -0
  54. package/dist/src/orgrt/completion-gate.js +86 -0
  55. package/dist/src/orgrt/completion-gate.js.map +1 -0
  56. package/dist/src/orgrt/daemon.d.ts +15 -0
  57. package/dist/src/orgrt/daemon.d.ts.map +1 -1
  58. package/dist/src/orgrt/daemon.js +194 -12
  59. package/dist/src/orgrt/daemon.js.map +1 -1
  60. package/dist/src/orgrt/file-roots.d.ts +57 -0
  61. package/dist/src/orgrt/file-roots.d.ts.map +1 -0
  62. package/dist/src/orgrt/file-roots.js +100 -0
  63. package/dist/src/orgrt/file-roots.js.map +1 -0
  64. package/dist/src/orgrt/policy-git.d.ts.map +1 -1
  65. package/dist/src/orgrt/policy-git.js +122 -4
  66. package/dist/src/orgrt/policy-git.js.map +1 -1
  67. package/dist/src/orgrt/policy.d.ts +13 -1
  68. package/dist/src/orgrt/policy.d.ts.map +1 -1
  69. package/dist/src/orgrt/policy.js +60 -11
  70. package/dist/src/orgrt/policy.js.map +1 -1
  71. package/dist/src/orgrt/reporting.d.ts +56 -0
  72. package/dist/src/orgrt/reporting.d.ts.map +1 -1
  73. package/dist/src/orgrt/reporting.js +42 -3
  74. package/dist/src/orgrt/reporting.js.map +1 -1
  75. package/dist/src/orgrt/role-sandbox.d.ts.map +1 -1
  76. package/dist/src/orgrt/role-sandbox.js +19 -49
  77. package/dist/src/orgrt/role-sandbox.js.map +1 -1
  78. package/dist/src/orgrt/scheduler-integration.d.ts.map +1 -1
  79. package/dist/src/orgrt/scheduler-integration.js +4 -2
  80. package/dist/src/orgrt/scheduler-integration.js.map +1 -1
  81. package/dist/src/orgrt/session.d.ts +5 -2
  82. package/dist/src/orgrt/session.d.ts.map +1 -1
  83. package/dist/src/orgrt/session.js +51 -7
  84. package/dist/src/orgrt/session.js.map +1 -1
  85. package/dist/src/orgrt/task-dag.d.ts +11 -0
  86. package/dist/src/orgrt/task-dag.d.ts.map +1 -1
  87. package/dist/src/orgrt/task-dag.js +19 -0
  88. package/dist/src/orgrt/task-dag.js.map +1 -1
  89. package/dist/src/orgrt/types.d.ts +6 -0
  90. package/dist/src/orgrt/types.d.ts.map +1 -1
  91. package/dist/src/orgrt/types.js +10 -0
  92. package/dist/src/orgrt/types.js.map +1 -1
  93. package/dist/src/prompt.d.ts.map +1 -1
  94. package/dist/src/prompt.js +14 -0
  95. package/dist/src/prompt.js.map +1 -1
  96. package/dist/src/services/crash-consent.d.ts +35 -0
  97. package/dist/src/services/crash-consent.d.ts.map +1 -0
  98. package/dist/src/services/crash-consent.js +100 -0
  99. package/dist/src/services/crash-consent.js.map +1 -0
  100. package/dist/src/services/crash-lock.d.ts +22 -0
  101. package/dist/src/services/crash-lock.d.ts.map +1 -0
  102. package/dist/src/services/crash-lock.js +86 -0
  103. package/dist/src/services/crash-lock.js.map +1 -0
  104. package/dist/src/services/crash-race-timeout.d.ts +13 -0
  105. package/dist/src/services/crash-race-timeout.d.ts.map +1 -0
  106. package/dist/src/services/crash-race-timeout.js +15 -0
  107. package/dist/src/services/crash-race-timeout.js.map +1 -0
  108. package/dist/src/services/crash-reporter.d.ts +12 -4
  109. package/dist/src/services/crash-reporter.d.ts.map +1 -1
  110. package/dist/src/services/crash-reporter.js +105 -129
  111. package/dist/src/services/crash-reporter.js.map +1 -1
  112. package/dist/src/ui/dashboard.html +122 -0
  113. package/dist/src/ui/mastermind-diagram-fallback.html +14 -0
  114. package/dist/src/ui/orgs.html +12 -0
  115. package/dist/src/ui/routes-monoes.mjs +105 -21
  116. package/dist/src/utils/redaction.d.ts +17 -0
  117. package/dist/src/utils/redaction.d.ts.map +1 -1
  118. package/dist/src/utils/redaction.js +52 -7
  119. package/dist/src/utils/redaction.js.map +1 -1
  120. package/dist/tsconfig.tsbuildinfo +1 -1
  121. package/package.json +6 -6
@@ -11,6 +11,11 @@
11
11
  import crypto from 'node:crypto';
12
12
  import fs from 'node:fs';
13
13
  import path from 'node:path';
14
+ import {
15
+ buildMonoesMcpEntry,
16
+ detectMonoesTokenLeak,
17
+ formatMonoesLeakWarning,
18
+ } from '../mcp/monoes-mcp-entry.mjs';
14
19
 
15
20
  const MONOES_BASE_URL = process.env.MONOMIND_MONOES_URL || 'https://monoes.me';
16
21
  const MONOES_SCOPE = 'community:read community:write offline_access';
@@ -22,6 +27,25 @@ const MONOES_SCOPE = 'community:read community:write offline_access';
22
27
  const _pendingStates = new Map();
23
28
  const STATE_TTL_MS = 10 * 60 * 1000;
24
29
 
30
+ // i-066 reviewer finding 4: detectMonoesTokenLeak() shells out to git;
31
+ // throttle it to at most once per this interval per process instead of
32
+ // once per dashboard status poll (the leak condition changes on the order
33
+ // of "never", not per poll — see the /api/monoes/status handler below).
34
+ let _lastLeakCheckAt = 0;
35
+ const _leakCheckIntervalMs = 60_000;
36
+
37
+ // i-066 follow-up finding 10 [MINOR]: this module-level throttle is shared
38
+ // across every test in the same file (the module is imported once per test
39
+ // file, not reset between `it()` blocks) — an earlier test's status poll
40
+ // can silently suppress a later test's leak check for up to
41
+ // _leakCheckIntervalMs of real time, for a reason unrelated to what that
42
+ // later test is actually asserting. Test-only escape hatch so tests can
43
+ // reset it in beforeEach instead of reaching for fake timers to defeat a
44
+ // throttle they don't otherwise need to think about.
45
+ export function __resetMonoesLeakThrottle() {
46
+ _lastLeakCheckAt = 0;
47
+ }
48
+
25
49
  function _connectionFile(monomindHome) {
26
50
  return path.join(monomindHome, '.monomind', 'monoes-connection.json');
27
51
  }
@@ -90,19 +114,14 @@ async function _getOrRegisterClientId(monomindHome, redirectUri) {
90
114
  return clientId;
91
115
  }
92
116
 
93
- function _buildMonoesMcpEntry(accessToken) {
94
- return {
95
- type: 'http',
96
- url: `${MONOES_BASE_URL}/api/mcp`,
97
- headers: { Authorization: `Bearer ${accessToken}` },
98
- };
99
- }
100
-
101
117
  /** Merges (or removes) the `monoes` entry in the project's existing
102
118
  * .mcp.json. Only touches that one key — never creates or rewrites the
103
119
  * rest of the file, since .mcp.json is otherwise owned by `init`/the user.
104
- * No-ops if .mcp.json doesn't exist yet (nothing to merge into). */
105
- function _syncMonoesMcpEntry(projectDir, accessToken) {
120
+ * No-ops if .mcp.json doesn't exist yet (nothing to merge into).
121
+ * `hasConnection` is a boolean, not a token — the entry is a local stdio
122
+ * proxy (mcp/monoes-proxy.ts) that resolves the Authorization header itself
123
+ * at request time, so there is no token to embed here at all. */
124
+ function _syncMonoesMcpEntry(projectDir, hasConnection) {
106
125
  const mcpPath = path.join(projectDir, '.mcp.json');
107
126
  let config;
108
127
  try {
@@ -111,8 +130,8 @@ function _syncMonoesMcpEntry(projectDir, accessToken) {
111
130
  return;
112
131
  }
113
132
  config.mcpServers = config.mcpServers || {};
114
- if (accessToken) {
115
- config.mcpServers.monoes = _buildMonoesMcpEntry(accessToken);
133
+ if (hasConnection) {
134
+ config.mcpServers.monoes = buildMonoesMcpEntry();
116
135
  } else {
117
136
  delete config.mcpServers.monoes;
118
137
  }
@@ -244,7 +263,7 @@ export async function handleMonoesRoutes(req, res, url, corsOrigin, ctx) {
244
263
  expiresAt: Date.now() + (tokenData.expires_in || 3600) * 1000,
245
264
  connectedUsername: me.username || null,
246
265
  });
247
- _syncMonoesMcpEntry(path.resolve(projectDir || process.cwd()), tokenData.access_token);
266
+ _syncMonoesMcpEntry(path.resolve(projectDir || process.cwd()), !!tokenData.access_token);
248
267
 
249
268
  closeTab('Connected to monoes.me — you can close this tab.');
250
269
  } catch (err) {
@@ -255,21 +274,86 @@ export async function handleMonoesRoutes(req, res, url, corsOrigin, ctx) {
255
274
 
256
275
  // ---------------------------------------------------- GET /api/monoes/status
257
276
  // Polled on every dashboard load — piggybacks the silent-refresh check so
258
- // .mcp.json's embedded access token self-heals (refreshed or removed)
259
- // roughly as often as the dashboard is opened, instead of only on the
260
- // explicit connect/disconnect actions.
277
+ // .mcp.json's entry self-heals (added/removed/migrated) roughly as often
278
+ // as the dashboard is opened, instead of only on the explicit
279
+ // connect/disconnect actions. Since the entry no longer embeds a token
280
+ // (it's a stdio proxy that resolves the header itself — see
281
+ // mcp/monoes-mcp-entry.mjs), a refresh that only changes the *value* of
282
+ // the token no longer requires a re-sync; only a change in *whether*
283
+ // .mcp.json's actual current entry matches the actual current connection
284
+ // state does (checked directly against the file, so this self-heals even
285
+ // if .mcp.json drifted from the connection for some other reason — a hand
286
+ // edit, a stale/missing file, etc). Reviewer i-066 finding 2: "matches"
287
+ // must be shape-aware, not presence-aware — a pre-fix entry that still
288
+ // carries a literal `headers`/`type: 'http'` bearer shape counts as
289
+ // needing a re-sync too, or a connected user whose .mcp.json already
290
+ // leaked the token is warned forever but never migrated.
261
291
  if (req.method === 'GET' && url === '/api/monoes/status') {
262
292
  const beforeConn = readMonoesConnection(MONOMIND_HOME);
263
293
  const validToken = /* value */ beforeConn?.accessToken
264
294
  ? await getValidMonoesToken(MONOMIND_HOME)
265
295
  : null;
266
296
  const afterConn = readMonoesConnection(MONOMIND_HOME);
267
- if (validToken !== (beforeConn?.accessToken || null)) {
268
- _syncMonoesMcpEntry(path.resolve(projectDir || process.cwd()), validToken);
297
+ const isConnected = !!validToken;
298
+
299
+ const resolvedProjectDir = path.resolve(projectDir || process.cwd());
300
+ let entry;
301
+ try {
302
+ const currentMcp = JSON.parse(
303
+ fs.readFileSync(path.join(resolvedProjectDir, '.mcp.json'), 'utf8'),
304
+ );
305
+ entry = currentMcp?.mcpServers?.monoes;
306
+ } catch {
307
+ entry = undefined; // No .mcp.json, or unreadable — nothing to sync into; _syncMonoesMcpEntry no-ops too.
308
+ }
309
+ const hasEntry = !!entry;
310
+ // i-066 reviewer finding 8 [BLOCKER]: `'headers' in entry` throws a
311
+ // TypeError when entry isn't an object — a realistic shape for a file
312
+ // designed to be committed and merged (a typo, a hand edit, a bad merge
313
+ // resolution can leave mcpServers.monoes as a string/number/boolean/
314
+ // array). That throw would escape this handler uncaught, and
315
+ // ui/server.mjs's http.createServer callback has no enclosing
316
+ // try/catch, so it would kill the whole dashboard process. Guard with
317
+ // an explicit object check first — a non-object (or array) value is
318
+ // simply non-conforming, so it self-heals via the normal re-sync path
319
+ // instead of crashing.
320
+ const isObjectEntry = typeof entry === 'object' && entry !== null && !Array.isArray(entry);
321
+ const isConformingEntry = isObjectEntry && !('headers' in entry) && entry.type !== 'http';
322
+
323
+ // i-066 §3.5: if this project already leaked the token (a legacy literal
324
+ // bearer entry still in .mcp.json, or monoes-connection.json tracked by
325
+ // git), warn loudly on every status poll rather than migrating silently.
326
+ // Reviewer i-066 finding 4: detectMonoesTokenLeak() shells out to git —
327
+ // throttle to at most once per _leakCheckIntervalMs per process rather
328
+ // than spawning a subprocess on every single-threaded-server poll; the
329
+ // condition it detects changes on the order of "never", not per poll.
330
+ //
331
+ // Reviewer i-066 finding U5 [BLOCKER]: this MUST run and be SNAPSHOTTED
332
+ // before _syncMonoesMcpEntry below. detectMonoesTokenLeak() re-reads
333
+ // .mcp.json from disk, and _syncMonoesMcpEntry rewrites that same file —
334
+ // running the leak check after the migration inspects the
335
+ // ALREADY-MIGRATED file and always finds nothing. A connected victim's
336
+ // first-ever poll would migrate the token out of the file silently and
337
+ // never warn that it may already be committed and on teammates'
338
+ // machines — the exact silent-failure mode this warning exists to
339
+ // prevent. Compute (and throttle) the check here; only print it after
340
+ // the migration has actually happened, so one poll does both.
341
+ const now = Date.now();
342
+ let leakWarning = null;
343
+ if (now - _lastLeakCheckAt > _leakCheckIntervalMs) {
344
+ _lastLeakCheckAt = now;
345
+ leakWarning = formatMonoesLeakWarning(await detectMonoesTokenLeak(resolvedProjectDir));
346
+ }
347
+
348
+ if (isConnected !== hasEntry || (hasEntry && !isConformingEntry)) {
349
+ _syncMonoesMcpEntry(resolvedProjectDir, isConnected);
269
350
  }
351
+
352
+ if (leakWarning) console.error(leakWarning);
353
+
270
354
  _json(res, corsOrigin, 200, {
271
- connected: !!validToken,
272
- username: validToken ? afterConn?.connectedUsername || null : null,
355
+ connected: isConnected,
356
+ username: isConnected ? afterConn?.connectedUsername || null : null,
273
357
  });
274
358
  return true;
275
359
  }
@@ -277,7 +361,7 @@ export async function handleMonoesRoutes(req, res, url, corsOrigin, ctx) {
277
361
  // ------------------------------------------------ POST /api/monoes/disconnect
278
362
  if (req.method === 'POST' && url === '/api/monoes/disconnect') {
279
363
  _deleteMonoesConnection(MONOMIND_HOME);
280
- _syncMonoesMcpEntry(path.resolve(projectDir || process.cwd()), null);
364
+ _syncMonoesMcpEntry(path.resolve(projectDir || process.cwd()), false);
281
365
  _json(res, corsOrigin, 200, { connected: false });
282
366
  return true;
283
367
  }
@@ -19,6 +19,23 @@ export declare function redactSecrets(text: string): string;
19
19
  * `<user>`'s neighborhood correctly), and secret-pattern stripping runs
20
20
  * before that path collapse too (a secret string that happens to look
21
21
  * path-like should still hit the secret patterns first).
22
+ *
23
+ * i-116-redact: secret-pattern stripping now runs BEFORE stripSsnAndPhone(),
24
+ * not after. This is a hardening change, not a fix to any currently-shipped
25
+ * behaviour — verified (reviewer, through the real shipped redact()) that
26
+ * both orders leak identically for every pattern that existed before this
27
+ * item. The shipped keyword patterns use a permissive value class
28
+ * (`[^\s'"]`), which still matches through a `<phone>`/`<ssn>` placeholder,
29
+ * so going second never broke them. This item's new self-identifying-prefix
30
+ * patterns use restrictive classes (e.g. `[A-Za-z0-9-]`) that a placeholder
31
+ * falls outside of, so a value with a phone-shaped digit run in the middle
32
+ * (Slack's `xoxb-<team-id>-<bot-id>-<secret>`, where the IDs are always
33
+ * numeric) would have its PII-mangled remainder no longer match — the
34
+ * secret suffix would then survive, untouched, in the final output. Secrets
35
+ * must get first pass at the text: a cosmetic PII transform must never be
36
+ * able to defeat a security transform, independent of which patterns exist
37
+ * today, because the next pattern added after this one would inherit the
38
+ * same latent hazard otherwise.
22
39
  */
23
40
  export declare function redact(text: string): string;
24
41
  //# sourceMappingURL=redaction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"redaction.d.ts","sourceRoot":"","sources":["../../../src/utils/redaction.ts"],"names":[],"mappings":"AAgKA;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMhD;AAED,4DAA4D;AAC5D,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO9C;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAY3C"}
1
+ {"version":3,"file":"redaction.d.ts","sourceRoot":"","sources":["../../../src/utils/redaction.ts"],"names":[],"mappings":"AA4LA;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMhD;AAED,4DAA4D;AAC5D,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO9C;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAY3C"}
@@ -62,15 +62,43 @@ function stripSsnAndPhone(text) {
62
62
  return out;
63
63
  }
64
64
  const SECRET_PATTERNS = [
65
- /(?:api[_-]?key|apikey)\s*[:=]\s*['"]?[^\s'"]{8,}['"]?/gi,
66
- /(?:secret|password|passwd|pwd)\s*[:=]\s*['"]?[^\s'"]{8,}['"]?/gi,
67
- /(?:token|bearer)\s*[:=]\s*['"]?[^\s'"]{10,}['"]?/gi,
65
+ // i-116-redact: `['"]?` inserted before `\s*[:=]` in these three so a
66
+ // quoted JSON key (`"accessToken":`, `"apiKey":`, `"secret":`) matches —
67
+ // previously the quote sat between the keyword and the colon and none of
68
+ // these fired on real JSON at all, the single most common shape.
69
+ /(?:api[_-]?key|apikey)['"]?\s*[:=]\s*['"]?[^\s'"]{8,}['"]?/gi,
70
+ /(?:secret|password|passwd|pwd)['"]?\s*[:=]\s*['"]?[^\s'"]{8,}['"]?/gi,
71
+ /(?:token|bearer)['"]?\s*[:=]\s*['"]?[^\s'"]{10,}['"]?/gi,
72
+ // i-116-redact: delimiterless header shape (`Authorization: Bearer <tok>`)
73
+ // has no `:`/`=` between "bearer" and the value at all — a space only —
74
+ // so none of the three keyword patterns above ever fired on it.
75
+ /\bbearer\s+['"]?[^\s'"]{10,}['"]?/gi,
68
76
  /-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/g,
69
77
  /sk-ant-[a-zA-Z0-9_-]{20,}/g,
70
78
  /sk-[a-zA-Z0-9_-]{20,}/g,
71
- /ghp_[a-zA-Z0-9]{36}/g,
72
- /gho_[a-zA-Z0-9]{36}/g,
73
- /npm_[a-zA-Z0-9]{36}/g,
79
+ // i-116-redact: self-identifying credential prefixes — the prefix itself
80
+ // carries the specificity, so a generous length bound costs nothing (it
81
+ // only widens what's caught, never what's falsely caught) and needs no
82
+ // keyword or delimiter at all. Replaces the old exact-{36} ghp_/gho_/npm_
83
+ // patterns, which only matched a conformant classic-format value and
84
+ // missed GitHub's current fine-grained format (`github_pat_`) entirely —
85
+ // the credential most likely to be present, since crash-reporter.ts files
86
+ // issues to GitHub.
87
+ //
88
+ // Deliberately NOT `\b`-anchored (review finding 1, round 2): the old
89
+ // ghp_/gho_/npm_ patterns these replace had no boundary assertion either,
90
+ // and adding one narrows coverage relative to what it replaces — a value
91
+ // glued directly onto a preceding word character (`Xghp_<36 chars>`, e.g.
92
+ // a log line with no separator before the token) would stop matching.
93
+ // The prefix plus the length bound already supplies all the specificity
94
+ // a `\b` would add; dropping it costs no precision and is measurably
95
+ // faster (no boundary check per candidate position).
96
+ /gh[pousr]_[A-Za-z0-9]{20,}/g, // GitHub classic PAT/OAuth/user/server/refresh
97
+ /github_pat_[A-Za-z0-9_]{20,}/g, // GitHub fine-grained (current format)
98
+ /glpat-[A-Za-z0-9_-]{16,}/g, // GitLab
99
+ /xox[abprs]-[A-Za-z0-9-]{10,}/g, // Slack (bot/app/admin/refresh/other)
100
+ /sk_(?:live|test)_[A-Za-z0-9]{16,}/g, // Stripe
101
+ /npm_[A-Za-z0-9]{20,}/g, // npm, widened from {36}
74
102
  /AKIA[0-9A-Z]{16}/g,
75
103
  /eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}/g, // JWT
76
104
  /[a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^:\s]+:[^@\s]+@[^\s'"]+/g, // user:pass@host connection strings
@@ -173,6 +201,23 @@ export function redactSecrets(text) {
173
201
  * `<user>`'s neighborhood correctly), and secret-pattern stripping runs
174
202
  * before that path collapse too (a secret string that happens to look
175
203
  * path-like should still hit the secret patterns first).
204
+ *
205
+ * i-116-redact: secret-pattern stripping now runs BEFORE stripSsnAndPhone(),
206
+ * not after. This is a hardening change, not a fix to any currently-shipped
207
+ * behaviour — verified (reviewer, through the real shipped redact()) that
208
+ * both orders leak identically for every pattern that existed before this
209
+ * item. The shipped keyword patterns use a permissive value class
210
+ * (`[^\s'"]`), which still matches through a `<phone>`/`<ssn>` placeholder,
211
+ * so going second never broke them. This item's new self-identifying-prefix
212
+ * patterns use restrictive classes (e.g. `[A-Za-z0-9-]`) that a placeholder
213
+ * falls outside of, so a value with a phone-shaped digit run in the middle
214
+ * (Slack's `xoxb-<team-id>-<bot-id>-<secret>`, where the IDs are always
215
+ * numeric) would have its PII-mangled remainder no longer match — the
216
+ * secret suffix would then survive, untouched, in the final output. Secrets
217
+ * must get first pass at the text: a cosmetic PII transform must never be
218
+ * able to defeat a security transform, independent of which patterns exist
219
+ * today, because the next pattern added after this one would inherit the
220
+ * same latent hazard otherwise.
176
221
  */
177
222
  export function redact(text) {
178
223
  const home = homedir();
@@ -180,8 +225,8 @@ export function redact(text) {
180
225
  out = stripGenericUserPrefixes(out);
181
226
  out = stripIPv4(out);
182
227
  out = stripEmail(out);
183
- out = stripSsnAndPhone(out);
184
228
  out = stripSecretPatterns(out);
229
+ out = stripSsnAndPhone(out);
185
230
  out = collapseAbsolutePaths(out);
186
231
  out = stripHostnames(out);
187
232
  out = stripIPv6(out);
@@ -1 +1 @@
1
- {"version":3,"file":"redaction.js","sourceRoot":"","sources":["../../../src/utils/redaction.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"redaction.js","sourceRoot":"","sources":["../../../src/utils/redaction.ts"],"names":[],"mappings":"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"}