@cybedefend/vibedefend 1.4.7 → 1.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.
Files changed (246) hide show
  1. package/README.md +77 -2
  2. package/dist/api/gateway-request.js +49 -0
  3. package/dist/api/gateway-request.js.map +1 -0
  4. package/dist/api/projects.js +67 -0
  5. package/dist/api/projects.js.map +1 -1
  6. package/dist/api/repository-link.js +157 -0
  7. package/dist/api/repository-link.js.map +1 -0
  8. package/dist/auth/auth-store.js +107 -25
  9. package/dist/auth/auth-store.js.map +1 -1
  10. package/dist/auth/auth.js +21 -0
  11. package/dist/auth/auth.js.map +1 -1
  12. package/dist/clients/cursor.js +5 -1
  13. package/dist/clients/cursor.js.map +1 -1
  14. package/dist/clients/vscode.js +38 -29
  15. package/dist/clients/vscode.js.map +1 -1
  16. package/dist/commands/mcp/allow.js +219 -0
  17. package/dist/commands/mcp/allow.js.map +1 -0
  18. package/dist/commands/mcp/connect.js +337 -0
  19. package/dist/commands/mcp/connect.js.map +1 -0
  20. package/dist/commands/mcp/index.js +170 -0
  21. package/dist/commands/mcp/index.js.map +1 -0
  22. package/dist/commands/mcp/proxy.js +264 -0
  23. package/dist/commands/mcp/proxy.js.map +1 -0
  24. package/dist/commands/mcp/scan.js +349 -0
  25. package/dist/commands/mcp/scan.js.map +1 -0
  26. package/dist/commands/mcp/sync.js +215 -0
  27. package/dist/commands/mcp/sync.js.map +1 -0
  28. package/dist/config.js +6 -0
  29. package/dist/config.js.map +1 -1
  30. package/dist/diagnostics.js +78 -12
  31. package/dist/diagnostics.js.map +1 -1
  32. package/dist/doctor.js +19 -0
  33. package/dist/doctor.js.map +1 -1
  34. package/dist/guards-evaluator/analysis-types.js +27 -0
  35. package/dist/guards-evaluator/analysis-types.js.map +1 -0
  36. package/dist/guards-evaluator/command-analysis.js +572 -0
  37. package/dist/guards-evaluator/command-analysis.js.map +1 -0
  38. package/dist/guards-evaluator/command-view.js +586 -0
  39. package/dist/guards-evaluator/command-view.js.map +1 -0
  40. package/dist/guards-evaluator/env.js +11 -0
  41. package/dist/guards-evaluator/env.js.map +1 -0
  42. package/dist/guards-evaluator/evaluate.js +91 -41
  43. package/dist/guards-evaluator/evaluate.js.map +1 -1
  44. package/dist/guards-evaluator/index.js +2 -1
  45. package/dist/guards-evaluator/index.js.map +1 -1
  46. package/dist/guards-evaluator/inline-code.js +259 -0
  47. package/dist/guards-evaluator/inline-code.js.map +1 -0
  48. package/dist/guards-evaluator/normalize.js +716 -0
  49. package/dist/guards-evaluator/normalize.js.map +1 -0
  50. package/dist/guards-evaluator/preprocess.js +13 -5
  51. package/dist/guards-evaluator/preprocess.js.map +1 -1
  52. package/dist/guards-evaluator/redact.js +19 -0
  53. package/dist/guards-evaluator/redact.js.map +1 -1
  54. package/dist/guards-evaluator/regex.js +25 -3
  55. package/dist/guards-evaluator/regex.js.map +1 -1
  56. package/dist/guards-evaluator/safe-commands.js +155 -0
  57. package/dist/guards-evaluator/safe-commands.js.map +1 -0
  58. package/dist/guards-evaluator/triage.js +315 -0
  59. package/dist/guards-evaluator/triage.js.map +1 -0
  60. package/dist/hook-runner.js +24873 -5068
  61. package/dist/hooks/install.js +38 -0
  62. package/dist/hooks/install.js.map +1 -1
  63. package/dist/hooks/runtime/config.js +38 -0
  64. package/dist/hooks/runtime/config.js.map +1 -1
  65. package/dist/hooks/runtime/emit.js +126 -53
  66. package/dist/hooks/runtime/emit.js.map +1 -1
  67. package/dist/hooks/runtime/fetch-rules.js +27 -7
  68. package/dist/hooks/runtime/fetch-rules.js.map +1 -1
  69. package/dist/hooks/runtime/gateway-http-error.js +34 -0
  70. package/dist/hooks/runtime/gateway-http-error.js.map +1 -0
  71. package/dist/hooks/runtime/guard-rules-cache.js +139 -17
  72. package/dist/hooks/runtime/guard-rules-cache.js.map +1 -1
  73. package/dist/hooks/runtime/guard-violations-buffer.js +321 -48
  74. package/dist/hooks/runtime/guard-violations-buffer.js.map +1 -1
  75. package/dist/hooks/runtime/judge-cache.js +6 -0
  76. package/dist/hooks/runtime/judge-cache.js.map +1 -1
  77. package/dist/hooks/runtime/judge-triage.js +193 -0
  78. package/dist/hooks/runtime/judge-triage.js.map +1 -0
  79. package/dist/hooks/runtime/judge.js +7 -1
  80. package/dist/hooks/runtime/judge.js.map +1 -1
  81. package/dist/hooks/runtime/pre-compact.js +21 -6
  82. package/dist/hooks/runtime/pre-compact.js.map +1 -1
  83. package/dist/hooks/runtime/resolve.js +108 -17
  84. package/dist/hooks/runtime/resolve.js.map +1 -1
  85. package/dist/hooks/runtime/retry-policy.js +57 -0
  86. package/dist/hooks/runtime/retry-policy.js.map +1 -0
  87. package/dist/hooks/runtime/review-sessions.js +74 -0
  88. package/dist/hooks/runtime/review-sessions.js.map +1 -0
  89. package/dist/hooks/runtime/script-resolve.js +695 -0
  90. package/dist/hooks/runtime/script-resolve.js.map +1 -0
  91. package/dist/hooks/runtime/session-activation.js +226 -0
  92. package/dist/hooks/runtime/session-activation.js.map +1 -0
  93. package/dist/hooks/runtime/session-review.js +174 -46
  94. package/dist/hooks/runtime/session-review.js.map +1 -1
  95. package/dist/hooks/runtime/session-start.js +35 -4
  96. package/dist/hooks/runtime/session-start.js.map +1 -1
  97. package/dist/hooks/runtime/session-writes.js +232 -0
  98. package/dist/hooks/runtime/session-writes.js.map +1 -0
  99. package/dist/hooks/runtime/sniff.js +26 -7
  100. package/dist/hooks/runtime/sniff.js.map +1 -1
  101. package/dist/hooks/runtime/target-resolve.js +336 -0
  102. package/dist/hooks/runtime/target-resolve.js.map +1 -0
  103. package/dist/hooks/runtime/unmapped-tools.js +93 -0
  104. package/dist/hooks/runtime/unmapped-tools.js.map +1 -0
  105. package/dist/hooks/runtime/usage-block.js +4 -0
  106. package/dist/hooks/runtime/usage-block.js.map +1 -1
  107. package/dist/hooks/runtime/user-prompt-submit.js +8 -2
  108. package/dist/hooks/runtime/user-prompt-submit.js.map +1 -1
  109. package/dist/hooks/runtime/wire-text.js +41 -0
  110. package/dist/hooks/runtime/wire-text.js.map +1 -0
  111. package/dist/hooks/runtime/work-dir.js +84 -0
  112. package/dist/hooks/runtime/work-dir.js.map +1 -0
  113. package/dist/index.js +45 -12
  114. package/dist/index.js.map +1 -1
  115. package/dist/install.js +174 -11
  116. package/dist/install.js.map +1 -1
  117. package/dist/link.js +74 -48
  118. package/dist/link.js.map +1 -1
  119. package/dist/login.js +99 -14
  120. package/dist/login.js.map +1 -1
  121. package/dist/mcp/auth/agent-sign-ins.js +174 -0
  122. package/dist/mcp/auth/agent-sign-ins.js.map +1 -0
  123. package/dist/mcp/auth/callback.js +200 -0
  124. package/dist/mcp/auth/callback.js.map +1 -0
  125. package/dist/mcp/auth/connect.js +392 -0
  126. package/dist/mcp/auth/connect.js.map +1 -0
  127. package/dist/mcp/auth/discovery.js +399 -0
  128. package/dist/mcp/auth/discovery.js.map +1 -0
  129. package/dist/mcp/auth/oauth.js +326 -0
  130. package/dist/mcp/auth/oauth.js.map +1 -0
  131. package/dist/mcp/auth/probe.js +128 -0
  132. package/dist/mcp/auth/probe.js.map +1 -0
  133. package/dist/mcp/auth/secrets.js +446 -0
  134. package/dist/mcp/auth/secrets.js.map +1 -0
  135. package/dist/mcp/auth/store.js +260 -0
  136. package/dist/mcp/auth/store.js.map +1 -0
  137. package/dist/mcp/auth/tokenSource.js +55 -0
  138. package/dist/mcp/auth/tokenSource.js.map +1 -0
  139. package/dist/mcp/config/atomicWrite.js +98 -0
  140. package/dist/mcp/config/atomicWrite.js.map +1 -0
  141. package/dist/mcp/config/clients.js +171 -0
  142. package/dist/mcp/config/clients.js.map +1 -0
  143. package/dist/mcp/config/cybedefend-servers.js +48 -0
  144. package/dist/mcp/config/cybedefend-servers.js.map +1 -0
  145. package/dist/mcp/config/discover.js +114 -0
  146. package/dist/mcp/config/discover.js.map +1 -0
  147. package/dist/mcp/config/hook.js +123 -0
  148. package/dist/mcp/config/hook.js.map +1 -0
  149. package/dist/mcp/config/index.js +11 -0
  150. package/dist/mcp/config/index.js.map +1 -0
  151. package/dist/mcp/config/install.js +132 -0
  152. package/dist/mcp/config/install.js.map +1 -0
  153. package/dist/mcp/config/installed.js +37 -0
  154. package/dist/mcp/config/installed.js.map +1 -0
  155. package/dist/mcp/config/jsonEdit.js +119 -0
  156. package/dist/mcp/config/jsonEdit.js.map +1 -0
  157. package/dist/mcp/config/lock.js +102 -0
  158. package/dist/mcp/config/lock.js.map +1 -0
  159. package/dist/mcp/config/proxyBinary.js +211 -0
  160. package/dist/mcp/config/proxyBinary.js.map +1 -0
  161. package/dist/mcp/config/rewrite.js +388 -0
  162. package/dist/mcp/config/rewrite.js.map +1 -0
  163. package/dist/mcp/config/types.js +34 -0
  164. package/dist/mcp/config/types.js.map +1 -0
  165. package/dist/mcp/proxy/audit.js +83 -0
  166. package/dist/mcp/proxy/audit.js.map +1 -0
  167. package/dist/mcp/proxy/authInterceptor.js +119 -0
  168. package/dist/mcp/proxy/authInterceptor.js.map +1 -0
  169. package/dist/mcp/proxy/expand.js +93 -0
  170. package/dist/mcp/proxy/expand.js.map +1 -0
  171. package/dist/mcp/proxy/inject.js +397 -0
  172. package/dist/mcp/proxy/inject.js.map +1 -0
  173. package/dist/mcp/proxy/intercept.js +37 -0
  174. package/dist/mcp/proxy/intercept.js.map +1 -0
  175. package/dist/mcp/proxy/jsonrpc.js +153 -0
  176. package/dist/mcp/proxy/jsonrpc.js.map +1 -0
  177. package/dist/mcp/proxy/log.js +109 -0
  178. package/dist/mcp/proxy/log.js.map +1 -0
  179. package/dist/mcp/proxy/paths.js +53 -0
  180. package/dist/mcp/proxy/paths.js.map +1 -0
  181. package/dist/mcp/proxy/proxy.js +510 -0
  182. package/dist/mcp/proxy/proxy.js.map +1 -0
  183. package/dist/mcp/proxy/spec.js +203 -0
  184. package/dist/mcp/proxy/spec.js.map +1 -0
  185. package/dist/mcp/proxy/sse.js +77 -0
  186. package/dist/mcp/proxy/sse.js.map +1 -0
  187. package/dist/mcp/proxy/upstream.js +2 -0
  188. package/dist/mcp/proxy/upstream.js.map +1 -0
  189. package/dist/mcp/proxy/upstreamHttp.js +499 -0
  190. package/dist/mcp/proxy/upstreamHttp.js.map +1 -0
  191. package/dist/mcp/proxy/upstreamStdio.js +188 -0
  192. package/dist/mcp/proxy/upstreamStdio.js.map +1 -0
  193. package/dist/mcp/proxy/upstreams.js +143 -0
  194. package/dist/mcp/proxy/upstreams.js.map +1 -0
  195. package/dist/mcp/proxy/verifyInterceptor.js +559 -0
  196. package/dist/mcp/proxy/verifyInterceptor.js.map +1 -0
  197. package/dist/mcp/proxy/windowsCommand.js +99 -0
  198. package/dist/mcp/proxy/windowsCommand.js.map +1 -0
  199. package/dist/mcp/scan/args.js +228 -0
  200. package/dist/mcp/scan/args.js.map +1 -0
  201. package/dist/mcp/scan/results.js +253 -0
  202. package/dist/mcp/scan/results.js.map +1 -0
  203. package/dist/mcp/scan/types.js +40 -0
  204. package/dist/mcp/scan/types.js.map +1 -0
  205. package/dist/mcp/verify/api.js +475 -0
  206. package/dist/mcp/verify/api.js.map +1 -0
  207. package/dist/mcp/verify/backend.js +143 -0
  208. package/dist/mcp/verify/backend.js.map +1 -0
  209. package/dist/mcp/verify/cache.js +182 -0
  210. package/dist/mcp/verify/cache.js.map +1 -0
  211. package/dist/mcp/verify/contract-errors.js +198 -0
  212. package/dist/mcp/verify/contract-errors.js.map +1 -0
  213. package/dist/mcp/verify/digest.js +91 -0
  214. package/dist/mcp/verify/digest.js.map +1 -0
  215. package/dist/mcp/verify/factory.js +56 -0
  216. package/dist/mcp/verify/factory.js.map +1 -0
  217. package/dist/mcp/verify/identity.js +173 -0
  218. package/dist/mcp/verify/identity.js.map +1 -0
  219. package/dist/mcp/verify/policy-store.js +63 -0
  220. package/dist/mcp/verify/policy-store.js.map +1 -0
  221. package/dist/mcp/verify/policy.js +158 -0
  222. package/dist/mcp/verify/policy.js.map +1 -0
  223. package/dist/mcp/verify/pool.js +27 -0
  224. package/dist/mcp/verify/pool.js.map +1 -0
  225. package/dist/mcp/verify/token-refresh.js +44 -0
  226. package/dist/mcp/verify/token-refresh.js.map +1 -0
  227. package/dist/mcp/verify/token.js +67 -0
  228. package/dist/mcp/verify/token.js.map +1 -0
  229. package/dist/mcp/verify/verifier.js +1009 -0
  230. package/dist/mcp/verify/verifier.js.map +1 -0
  231. package/dist/org-gate.js +1 -1
  232. package/dist/org-gate.js.map +1 -1
  233. package/dist/org.js +146 -0
  234. package/dist/org.js.map +1 -0
  235. package/dist/project-create.js +129 -0
  236. package/dist/project-create.js.map +1 -0
  237. package/dist/prompts.js +21 -0
  238. package/dist/prompts.js.map +1 -1
  239. package/dist/re2.wasm +0 -0
  240. package/dist/status.js +61 -0
  241. package/dist/status.js.map +1 -1
  242. package/dist/uninstall.js +49 -4
  243. package/dist/uninstall.js.map +1 -1
  244. package/dist/utils.js +62 -6
  245. package/dist/utils.js.map +1 -1
  246. package/package.json +10 -3
@@ -0,0 +1,446 @@
1
+ /**
2
+ * Where a third-party MCP token is kept, per platform.
3
+ *
4
+ * One interface, four implementations, in decreasing order of protection:
5
+ *
6
+ * - macOS: the system keychain, through `security`, in a service of its own.
7
+ * - Linux: the session secret service, through `secret-tool` (libsecret).
8
+ * - Windows: DPAPI, through PowerShell's `ConvertFrom-SecureString`. The
9
+ * plan says "Credential Manager"; DPAPI is the primitive Credential
10
+ * Manager itself is built on, and it is the only one reachable without a
11
+ * native dependency — `cmdkey` can write a credential but cannot read its
12
+ * password back, which makes it useless to us. The ciphertext is bound to
13
+ * the user and the machine, and lands in the same file as the fallback.
14
+ * - Anywhere else, or when the above is unavailable: `tokens.enc`, AES-256-GCM
15
+ * under a key derived from a machine secret and a per-install salt.
16
+ *
17
+ * The last one is obfuscation, not protection, and says so out loud: anything
18
+ * running as this user can derive the same key. It exists so that a laptop
19
+ * without a session keyring keeps working, and it is announced every time it
20
+ * is used, as the plan requires.
21
+ *
22
+ * No token is ever logged, interpolated into an error message, or passed as a
23
+ * command-line argument — except on macOS, where `security` takes the value
24
+ * in `argv`. That one is inherited from the legacy implementation and noted
25
+ * in the Phase 2 summary.
26
+ */
27
+ import { execFileSync } from 'node:child_process';
28
+ import { createCipheriv, createDecipheriv, randomBytes, scryptSync, timingSafeEqual, } from 'node:crypto';
29
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
30
+ import { hostname, homedir, userInfo } from 'node:os';
31
+ import { join } from 'node:path';
32
+ import { mcpHomeDir, PROXY_ENV_PREFIX } from '../proxy/paths.js';
33
+ /**
34
+ * Keychain service dedicated to third-party MCP credentials.
35
+ *
36
+ * Deliberately not `"Codex MCP Credentials"`, where `src/auth/auth-store.ts`
37
+ * keeps the CybeDefend entries: a loose lookup of that service falling back
38
+ * to "the first entry found" could surface a Linear token as the CybeDefend
39
+ * one, which would then leave as `Authorization: Bearer` towards our own API.
40
+ * A separate service closes that structurally.
41
+ */
42
+ export const MCP_KEYCHAIN_SERVICE = 'CybeDefend MCP Server Credentials';
43
+ const COMMAND_TIMEOUT_MS = 5000;
44
+ function defaultExecFile(file, args, input) {
45
+ return execFileSync(file, args, {
46
+ encoding: 'utf8',
47
+ stdio: input === undefined ? ['ignore', 'pipe', 'ignore'] : ['pipe', 'pipe', 'ignore'],
48
+ input,
49
+ timeout: COMMAND_TIMEOUT_MS,
50
+ windowsHide: true,
51
+ }).trim();
52
+ }
53
+ function defaultAnnounce(detail) {
54
+ try {
55
+ process.stderr.write(`vibedefend: ${detail}\n`);
56
+ }
57
+ catch {
58
+ /* a message must never take the CLI down */
59
+ }
60
+ }
61
+ // ─── macOS ──────────────────────────────────────────────────────────────────
62
+ class MacosKeychain {
63
+ exec;
64
+ kind = 'macos-keychain';
65
+ constructor(exec) {
66
+ this.exec = exec;
67
+ }
68
+ get(key) {
69
+ try {
70
+ const blob = this.exec('security', [
71
+ 'find-generic-password',
72
+ '-s',
73
+ MCP_KEYCHAIN_SERVICE,
74
+ '-a',
75
+ key,
76
+ '-w',
77
+ ]);
78
+ return blob.trim() === '' ? null : blob.trim();
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ }
84
+ set(key, value) {
85
+ this.exec('security', [
86
+ 'add-generic-password',
87
+ '-U',
88
+ '-s',
89
+ MCP_KEYCHAIN_SERVICE,
90
+ '-a',
91
+ key,
92
+ '-w',
93
+ value,
94
+ ]);
95
+ }
96
+ delete(key) {
97
+ try {
98
+ this.exec('security', ['delete-generic-password', '-s', MCP_KEYCHAIN_SERVICE, '-a', key]);
99
+ }
100
+ catch {
101
+ /* absent, or the keychain is locked */
102
+ }
103
+ }
104
+ }
105
+ // ─── Linux ──────────────────────────────────────────────────────────────────
106
+ class LinuxSecretService {
107
+ exec;
108
+ kind = 'linux-secret-service';
109
+ constructor(exec) {
110
+ this.exec = exec;
111
+ }
112
+ get(key) {
113
+ try {
114
+ const blob = this.exec('secret-tool', [
115
+ 'lookup',
116
+ 'service',
117
+ MCP_KEYCHAIN_SERVICE,
118
+ 'account',
119
+ key,
120
+ ]);
121
+ return blob.trim() === '' ? null : blob.trim();
122
+ }
123
+ catch {
124
+ return null;
125
+ }
126
+ }
127
+ set(key, value) {
128
+ // The value goes in on stdin: `secret-tool store` reads it there
129
+ // precisely so it never appears in `/proc/<pid>/cmdline`.
130
+ this.exec('secret-tool', ['store', '--label', MCP_KEYCHAIN_SERVICE, 'service', MCP_KEYCHAIN_SERVICE, 'account', key], value);
131
+ }
132
+ delete(key) {
133
+ try {
134
+ this.exec('secret-tool', ['clear', 'service', MCP_KEYCHAIN_SERVICE, 'account', key]);
135
+ }
136
+ catch {
137
+ /* absent, or no session keyring */
138
+ }
139
+ }
140
+ }
141
+ // ─── Windows ────────────────────────────────────────────────────────────────
142
+ /**
143
+ * DPAPI, driven by PowerShell, with the ciphertext kept in `tokens.enc`.
144
+ *
145
+ * `ConvertFrom-SecureString` (no `-Key`) encrypts under the current user's
146
+ * DPAPI master key: the result is useless to another user and on another
147
+ * machine. Both directions read their input from stdin, never from `argv`,
148
+ * because a command line is visible to anything that can list processes.
149
+ */
150
+ class WindowsDpapi {
151
+ exec;
152
+ file;
153
+ kind = 'windows-dpapi';
154
+ constructor(exec, file) {
155
+ this.exec = exec;
156
+ this.file = file;
157
+ }
158
+ powershell(script, input) {
159
+ return this.exec('powershell.exe', ['-NoProfile', '-NonInteractive', '-NoLogo', '-Command', script], input);
160
+ }
161
+ get(key) {
162
+ const stored = this.file.readRaw(key);
163
+ if (!stored)
164
+ return null;
165
+ try {
166
+ const plain = this.powershell('$e = [Console]::In.ReadToEnd().Trim(); ' +
167
+ '$s = ConvertTo-SecureString -String $e; ' +
168
+ '[Runtime.InteropServices.Marshal]::PtrToStringBSTR(' +
169
+ '[Runtime.InteropServices.Marshal]::SecureStringToBSTR($s))', stored);
170
+ return plain.trim() === '' ? null : plain;
171
+ }
172
+ catch {
173
+ return null;
174
+ }
175
+ }
176
+ set(key, value) {
177
+ const encrypted = this.powershell('$p = [Console]::In.ReadToEnd(); ' +
178
+ '$s = ConvertTo-SecureString -String $p -AsPlainText -Force; ' +
179
+ 'ConvertFrom-SecureString -SecureString $s', value);
180
+ if (encrypted.trim() === '')
181
+ throw new Error('DPAPI returned an empty ciphertext');
182
+ this.file.writeRaw(key, encrypted.trim());
183
+ }
184
+ delete(key) {
185
+ this.file.writeRaw(key, null);
186
+ }
187
+ }
188
+ /**
189
+ * `tokens.enc`: AES-256-GCM, key derived with scrypt from a machine secret
190
+ * and a per-install salt.
191
+ *
192
+ * What this is: enough that a token is not readable in a backup, in a synced
193
+ * folder, or by a tool grepping dotfiles for `Bearer`. What it is not: a
194
+ * defence against code running as this user, which can derive the same key.
195
+ * Callers announce it; see `selectSecretBackend`.
196
+ */
197
+ export class EncryptedFileStore {
198
+ path;
199
+ machineSecretFn;
200
+ readFileFn;
201
+ writeFileFn;
202
+ kind = 'encrypted-file';
203
+ /**
204
+ * Keyed by salt, not by nothing.
205
+ *
206
+ * The salt is created with the envelope and never changes afterwards, but
207
+ * caching a key without remembering which salt produced it is how the first
208
+ * version of this class wrote a file it could not read back: `encrypt` read
209
+ * the envelope to get a salt, then `writeRaw` read it AGAIN — and a missing
210
+ * file yields a FRESH random salt every time — so the ciphertext went to
211
+ * disk under one key while the envelope recorded another. Everything worked
212
+ * inside the writing process, where the key was cached, and nothing worked
213
+ * in the next one.
214
+ */
215
+ keys = new Map();
216
+ constructor(path, machineSecretFn, readFileFn, writeFileFn) {
217
+ this.path = path;
218
+ this.machineSecretFn = machineSecretFn;
219
+ this.readFileFn = readFileFn;
220
+ this.writeFileFn = writeFileFn;
221
+ }
222
+ get(key) {
223
+ const envelope = this.load();
224
+ const raw = envelope.entries[key];
225
+ if (!raw)
226
+ return null;
227
+ try {
228
+ return this.decrypt(envelope.salt, raw);
229
+ }
230
+ catch {
231
+ // A ciphertext that no longer opens — the machine secret changed, or
232
+ // the file was tampered with — behaves like an absent credential.
233
+ return null;
234
+ }
235
+ }
236
+ set(key, value) {
237
+ const envelope = this.load();
238
+ envelope.entries[key] = this.encrypt(envelope.salt, value);
239
+ this.persist(envelope);
240
+ }
241
+ delete(key) {
242
+ const envelope = this.load();
243
+ delete envelope.entries[key];
244
+ this.persist(envelope);
245
+ }
246
+ /** Reads one entry without decrypting it. Used by the DPAPI backend. */
247
+ readRaw(key) {
248
+ return this.load().entries[key] ?? null;
249
+ }
250
+ /** Writes one entry as it is, or removes it when `value` is `null`. */
251
+ writeRaw(key, value) {
252
+ const envelope = this.load();
253
+ if (value === null)
254
+ delete envelope.entries[key];
255
+ else
256
+ envelope.entries[key] = value;
257
+ this.persist(envelope);
258
+ }
259
+ load() {
260
+ try {
261
+ const parsed = JSON.parse(this.readFileFn(this.path));
262
+ if (parsed && parsed.v === 1 && typeof parsed.salt === 'string' && parsed.entries) {
263
+ return { v: 1, salt: parsed.salt, entries: { ...parsed.entries } };
264
+ }
265
+ }
266
+ catch {
267
+ /* absent or unreadable: start a new envelope */
268
+ }
269
+ return { v: 1, salt: randomBytes(16).toString('base64'), entries: {} };
270
+ }
271
+ persist(envelope) {
272
+ this.writeFileFn(this.path, JSON.stringify(envelope, null, 2));
273
+ }
274
+ /** scrypt costs about 50 ms, and a session asks for the key more than once. */
275
+ keyFor(salt) {
276
+ const known = this.keys.get(salt);
277
+ if (known)
278
+ return known;
279
+ const derived = scryptSync(this.machineSecretFn(), Buffer.from(salt, 'base64'), 32);
280
+ this.keys.set(salt, derived);
281
+ return derived;
282
+ }
283
+ encrypt(salt, plain) {
284
+ const iv = randomBytes(12);
285
+ const cipher = createCipheriv('aes-256-gcm', this.keyFor(salt), iv, { authTagLength: 16 });
286
+ const body = Buffer.concat([cipher.update(plain, 'utf8'), cipher.final()]);
287
+ return [
288
+ iv.toString('base64'),
289
+ cipher.getAuthTag().toString('base64'),
290
+ body.toString('base64'),
291
+ ].join('.');
292
+ }
293
+ decrypt(salt, blob) {
294
+ const [ivPart, tagPart, bodyPart] = blob.split('.');
295
+ if (!ivPart || !tagPart || !bodyPart)
296
+ throw new Error('malformed ciphertext');
297
+ const decipher = createDecipheriv('aes-256-gcm', this.keyFor(salt), Buffer.from(ivPart, 'base64'), { authTagLength: 16 });
298
+ decipher.setAuthTag(Buffer.from(tagPart, 'base64'));
299
+ return Buffer.concat([
300
+ decipher.update(Buffer.from(bodyPart, 'base64')),
301
+ decipher.final(),
302
+ ]).toString('utf8');
303
+ }
304
+ }
305
+ export function tokensFile(dir) {
306
+ return join(dir ?? mcpHomeDir(), 'tokens.enc');
307
+ }
308
+ function defaultReadFile(path) {
309
+ if (!existsSync(path))
310
+ throw new Error('ENOENT: no such file');
311
+ return readFileSync(path, 'utf8');
312
+ }
313
+ function defaultWriteFile(path, content) {
314
+ // The mode is set AT CREATION, as in `auth-store.ts`: a `chmod` afterwards
315
+ // leaves the file readable for the length of a syscall, and on a shared
316
+ // machine that window is enough.
317
+ mkdirSync(join(path, '..'), { recursive: true, mode: 0o700 });
318
+ writeFileSync(path, content, { encoding: 'utf8', mode: 0o600 });
319
+ chmodSync(path, 0o600);
320
+ }
321
+ /**
322
+ * Something stable for this machine and this user, and cheap to read.
323
+ *
324
+ * Not a secret in the cryptographic sense — a machine id is readable by any
325
+ * local process — which is exactly why the file it keys is called a fallback.
326
+ */
327
+ export function machineSecret(platform = process.platform) {
328
+ const parts = [userInfo().username, homedir()];
329
+ try {
330
+ if (platform === 'linux') {
331
+ for (const candidate of ['/etc/machine-id', '/var/lib/dbus/machine-id']) {
332
+ if (existsSync(candidate)) {
333
+ parts.push(readFileSync(candidate, 'utf8').trim());
334
+ break;
335
+ }
336
+ }
337
+ }
338
+ else if (platform === 'darwin') {
339
+ const out = execFileSync('ioreg', ['-rd1', '-c', 'IOPlatformExpertDevice'], {
340
+ encoding: 'utf8',
341
+ timeout: COMMAND_TIMEOUT_MS,
342
+ stdio: ['ignore', 'pipe', 'ignore'],
343
+ });
344
+ const match = /"IOPlatformUUID"\s*=\s*"([^"]+)"/.exec(out);
345
+ if (match)
346
+ parts.push(match[1]);
347
+ }
348
+ else if (platform === 'win32') {
349
+ const out = execFileSync('reg', ['query', 'HKLM\\SOFTWARE\\Microsoft\\Cryptography', '/v', 'MachineGuid'], { encoding: 'utf8', timeout: COMMAND_TIMEOUT_MS, stdio: ['ignore', 'pipe', 'ignore'] });
350
+ const match = /MachineGuid\s+REG_SZ\s+(\S+)/.exec(out);
351
+ if (match)
352
+ parts.push(match[1]);
353
+ }
354
+ }
355
+ catch {
356
+ /* no machine id available: the hostname below still varies per machine */
357
+ }
358
+ parts.push(hostname());
359
+ return parts.join('|');
360
+ }
361
+ /**
362
+ * Picks the backend for this platform, and falls back to the encrypted file
363
+ * when it is not usable — an SSH session with no keyring, a locked keychain,
364
+ * a machine without `secret-tool`.
365
+ *
366
+ * The probe is a real round trip on a throwaway key rather than a version
367
+ * check: `secret-tool --version` succeeds on a machine whose D-Bus session
368
+ * has no secret service at all, which is exactly the case that has to
369
+ * degrade.
370
+ */
371
+ export function selectSecretBackend(deps = {}) {
372
+ const exec = deps.execFileFn ?? defaultExecFile;
373
+ const platform = deps.platform ?? process.platform;
374
+ // `VIBEDEFEND_MCP_SECRET_BACKEND=file` skips the platform store entirely.
375
+ // The test suite needs it — a suite that wrote into the developer's keychain
376
+ // would be exactly the damage the plan forbids for `~/.cybedefend/` — and it
377
+ // is the honest answer for a headless box whose keyring prompt nobody will
378
+ // ever see.
379
+ const forced = (deps.env ?? process.env)[`${PROXY_ENV_PREFIX}SECRET_BACKEND`];
380
+ const file = new EncryptedFileStore(
381
+ // `dir` wins, then whatever `VIBEDEFEND_MCP_DIR` says in the environment
382
+ // this call was handed. A command that scopes its own environment — every
383
+ // test does — must not have its credential file fall back to the real one.
384
+ tokensFile(deps.dir ?? mcpHomeDir(deps.env ?? process.env)), deps.machineSecretFn ?? (() => machineSecret(platform)), deps.readFileFn ?? defaultReadFile, deps.writeFileFn ?? defaultWriteFile);
385
+ const announce = deps.onFallback ?? defaultAnnounce;
386
+ if (forced === 'file')
387
+ return { backend: file, degraded: false };
388
+ const platformBackend = platform === 'darwin'
389
+ ? new MacosKeychain(exec)
390
+ : platform === 'linux'
391
+ ? new LinuxSecretService(exec)
392
+ : platform === 'win32'
393
+ ? new WindowsDpapi(exec, file)
394
+ : null;
395
+ if (!platformBackend) {
396
+ announce(`no OS credential store on ${platform} — MCP tokens are kept in ${tokensFile(deps.dir)}, ` +
397
+ 'encrypted under a key derived from this machine; anything running as you can read them');
398
+ return { backend: file, degraded: true };
399
+ }
400
+ const failure = probe(platformBackend);
401
+ if (!failure)
402
+ return { backend: platformBackend, degraded: false };
403
+ announce(`${platformBackend.kind} is unavailable (${failure}) — MCP tokens are kept in ${tokensFile(deps.dir)}, encrypted under a key derived from this machine; anything running as you can read them`);
404
+ return { backend: file, degraded: true };
405
+ }
406
+ /** The probe key. Written, read back, removed; never a real credential. */
407
+ const PROBE_KEY = 'vibedefend-availability-probe';
408
+ function probe(backend) {
409
+ const expected = randomBytes(16).toString('base64');
410
+ try {
411
+ backend.set(PROBE_KEY, expected);
412
+ const seen = backend.get(PROBE_KEY);
413
+ backend.delete(PROBE_KEY);
414
+ if (seen === null)
415
+ return 'the store accepted a write but returned nothing';
416
+ const a = Buffer.from(seen);
417
+ const b = Buffer.from(expected);
418
+ if (a.length !== b.length || !timingSafeEqual(a, b)) {
419
+ return 'the store returned a different value than the one written';
420
+ }
421
+ return null;
422
+ }
423
+ catch (error) {
424
+ try {
425
+ backend.delete(PROBE_KEY);
426
+ }
427
+ catch {
428
+ /* nothing to clean up */
429
+ }
430
+ // The diagnostic goes to stderr, so it must not carry the value the store
431
+ // was handed. Here that value is only the probe's, but the same code path
432
+ // is what a real credential travels through, and a store that echoes its
433
+ // input into an error message is common enough (`secret-tool` does).
434
+ const detail = error instanceof Error ? firstLine(error.message) : 'unknown failure';
435
+ return redact(detail, expected);
436
+ }
437
+ }
438
+ /** Removes a known secret from a message that is about to be printed. */
439
+ function redact(message, secret) {
440
+ return secret === '' ? message : message.split(secret).join('<redacted>');
441
+ }
442
+ function firstLine(message) {
443
+ const line = message.split('\n')[0]?.trim() ?? '';
444
+ return line.length > 160 ? `${line.slice(0, 160)}…` : line;
445
+ }
446
+ //# sourceMappingURL=secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../../src/mcp/auth/secrets.ts"],"names":[],"mappings":"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"}