@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,174 @@
1
+ /**
2
+ * The sign-ins the user's agents already hold for an MCP server.
3
+ *
4
+ * Putting the proxy in front of a server used to cost a second OAuth sign-in
5
+ * in the browser, for every server Claude Code or Codex was already signed in
6
+ * to. `vibedefend connect` now takes over the agent's sign-in first: once the
7
+ * entry is wrapped, the agent reaches that server through the proxy and no
8
+ * longer uses its own copy.
9
+ *
10
+ * What is read, and only for the EXACT server asked for (canonical URL, as
11
+ * the proxy's own store is keyed):
12
+ *
13
+ * - Claude Code: the `mcpOAuth` map of the `Claude Code-credentials` macOS
14
+ * keychain item, and of `~/.claude/.credentials.json` (where Claude Code
15
+ * keeps it off macOS; `CLAUDE_CONFIG_DIR` moves it). Claude Code writes
16
+ * that item with the `security` tool, so reading it asks nothing.
17
+ * - Codex: its file store, `$CODEX_HOME/.credentials.json` (default
18
+ * `~/.codex`). Never its keychain items: Codex writes them through the
19
+ * native keychain API, so `security` cannot read them without macOS asking
20
+ * the user, once per server (measured 2026-10-20: errSecUserCanceled).
21
+ *
22
+ * Cursor and Windsurf keep theirs in their own databases: not read.
23
+ *
24
+ * `VIBEDEFEND_AGENT_SIGN_INS=off` reads none of it (the test suite sets it:
25
+ * no test may read the developer's credentials). `vibedefend connect
26
+ * --no-reuse` does the same for one run.
27
+ *
28
+ * Never throws, never logs: an unreadable store is an empty one, and what is
29
+ * read is a credential.
30
+ */
31
+ import { execFileSync } from 'node:child_process';
32
+ import { readFileSync } from 'node:fs';
33
+ import { homedir, userInfo } from 'node:os';
34
+ import { join } from 'node:path';
35
+ import { canonicalMcpUrl } from './oauth.js';
36
+ /** How each agent is named to the user. */
37
+ export const AGENT_SIGN_IN_LABELS = {
38
+ 'claude-code': 'Claude Code',
39
+ codex: 'Codex',
40
+ };
41
+ const CLAUDE_CODE_KEYCHAIN_SERVICE = 'Claude Code-credentials';
42
+ /** Every sign-in the agents hold for `serverUrl`, Claude Code first. */
43
+ export function findAgentSignIns(serverUrl, deps = {}) {
44
+ const wanted = canonicalMcpUrl(serverUrl);
45
+ if (!wanted)
46
+ return [];
47
+ const env = deps.env ?? process.env;
48
+ if (env.VIBEDEFEND_AGENT_SIGN_INS === 'off')
49
+ return [];
50
+ const home = env.HOME ?? env.USERPROFILE ?? homedir();
51
+ const found = [];
52
+ const add = (signIn) => {
53
+ if (!signIn)
54
+ return;
55
+ const duplicate = found.some((known) => known.clientId === signIn.clientId &&
56
+ known.accessToken === signIn.accessToken &&
57
+ known.refreshToken === signIn.refreshToken);
58
+ if (!duplicate)
59
+ found.push(signIn);
60
+ };
61
+ if ((deps.platform ?? process.platform) === 'darwin') {
62
+ const read = deps.readKeychain ?? readMacOSKeychain;
63
+ const blob = quietly(() => read(CLAUDE_CODE_KEYCHAIN_SERVICE, deps.username ?? loginName()));
64
+ for (const signIn of claudeCodeSignIns(blob, wanted))
65
+ add(signIn);
66
+ }
67
+ const claudeDir = env.CLAUDE_CONFIG_DIR ?? join(home, '.claude');
68
+ for (const signIn of claudeCodeSignIns(readQuietly(join(claudeDir, '.credentials.json')), wanted))
69
+ add(signIn);
70
+ const codexDir = env.CODEX_HOME ?? join(home, '.codex');
71
+ for (const signIn of codexSignIns(readQuietly(join(codexDir, '.credentials.json')), wanted))
72
+ add(signIn);
73
+ return found;
74
+ }
75
+ function claudeCodeSignIns(blob, wanted) {
76
+ const data = parseObject(blob);
77
+ const entries = data && isObject(data.mcpOAuth) ? Object.values(data.mcpOAuth) : [];
78
+ return entries.flatMap((entry) => {
79
+ if (!isObject(entry) || !sameServer(entry.serverUrl, wanted))
80
+ return [];
81
+ const signIn = signInFrom('claude-code', {
82
+ accessToken: entry.accessToken,
83
+ refreshToken: entry.refreshToken,
84
+ expiresAt: entry.expiresAt,
85
+ clientId: entry.clientId,
86
+ clientSecret: entry.clientSecret,
87
+ issuer: entry.issuer,
88
+ });
89
+ return signIn ? [signIn] : [];
90
+ });
91
+ }
92
+ function codexSignIns(blob, wanted) {
93
+ const data = parseObject(blob);
94
+ return Object.values(data ?? {}).flatMap((entry) => {
95
+ if (!isObject(entry) || !sameServer(entry.server_url ?? entry.url, wanted))
96
+ return [];
97
+ const response = isObject(entry.token_response) ? entry.token_response : {};
98
+ const signIn = signInFrom('codex', {
99
+ accessToken: entry.access_token ?? response.access_token,
100
+ refreshToken: entry.refresh_token ?? response.refresh_token,
101
+ expiresAt: entry.expires_at,
102
+ clientId: entry.client_id,
103
+ clientSecret: entry.client_secret,
104
+ issuer: null,
105
+ });
106
+ return signIn ? [signIn] : [];
107
+ });
108
+ }
109
+ function signInFrom(source, raw) {
110
+ const clientId = text(raw.clientId);
111
+ const accessToken = text(raw.accessToken);
112
+ const refreshToken = text(raw.refreshToken);
113
+ if (!clientId || (!accessToken && !refreshToken))
114
+ return null;
115
+ return {
116
+ source,
117
+ accessToken,
118
+ refreshToken,
119
+ expiresAt: epochMs(raw.expiresAt),
120
+ clientId,
121
+ clientSecret: text(raw.clientSecret),
122
+ issuer: text(raw.issuer),
123
+ };
124
+ }
125
+ function sameServer(url, wanted) {
126
+ return typeof url === 'string' && canonicalMcpUrl(url) === wanted;
127
+ }
128
+ /** Claude Code and Codex record milliseconds; a value below 1e11 can only be seconds. */
129
+ function epochMs(value) {
130
+ if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0)
131
+ return null;
132
+ return value < 1e11 ? value * 1000 : value;
133
+ }
134
+ function text(value) {
135
+ return typeof value === 'string' && value !== '' ? value : null;
136
+ }
137
+ function isObject(value) {
138
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
139
+ }
140
+ function parseObject(blob) {
141
+ if (!blob)
142
+ return null;
143
+ try {
144
+ const parsed = JSON.parse(blob);
145
+ return isObject(parsed) ? parsed : null;
146
+ }
147
+ catch {
148
+ return null;
149
+ }
150
+ }
151
+ function quietly(read) {
152
+ try {
153
+ return read();
154
+ }
155
+ catch {
156
+ return null;
157
+ }
158
+ }
159
+ function readQuietly(path) {
160
+ return quietly(() => readFileSync(path, 'utf8'));
161
+ }
162
+ function loginName() {
163
+ try {
164
+ return userInfo().username;
165
+ }
166
+ catch {
167
+ return undefined;
168
+ }
169
+ }
170
+ function readMacOSKeychain(service, account) {
171
+ const blob = execFileSync('security', ['find-generic-password', '-s', service, ...(account === undefined ? [] : ['-a', account]), '-w'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 2000 }).trim();
172
+ return blob === '' ? null : blob;
173
+ }
174
+ //# sourceMappingURL=agent-sign-ins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-sign-ins.js","sourceRoot":"","sources":["../../../src/mcp/auth/agent-sign-ins.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * The loopback callback server of the MCP authorization flow (RFC 8252).
3
+ *
4
+ * ─── Why `state` and `iss` are checked HERE ─────────────────────────────────
5
+ *
6
+ * `discovery.ts` binds the authorization server's metadata to the MCP server
7
+ * being asked. That check closes an INSTANCE of the mix-up, not the class:
8
+ * the attacker only has to host a 302 on THEIR OWN `authorization_endpoint`
9
+ * — an endpoint that opens in the BROWSER, never fetched by us, so
10
+ * structurally invisible to anything we could check on the metadata. The
11
+ * browser then lands on the REAL consent page of a genuine third party, with
12
+ * THEIR `client_id` and OUR `code_challenge`; that third party redirects to
13
+ * our loopback with a code that is VALID AT THEIR END. Without a further
14
+ * defence the exchange would send that code — and our `code_verifier` — to
15
+ * the attacker's SELF-DECLARED `token_endpoint`.
16
+ *
17
+ * Two standard defences answer that:
18
+ *
19
+ * • `state` — random, single-use, bound to THIS attempt. A response
20
+ * carrying an unknown or ALREADY CONSUMED state is rejected. It closes
21
+ * the class UNCONDITIONALLY as an anti-CSRF measure, and depends on no
22
+ * capability of the third party.
23
+ * • `iss` (RFC 9207) — the issuer announced BY THE AUTHORIZATION RESPONSE
24
+ * ITSELF, so by the REAL third party that handled it and never by a
25
+ * document the attacker controls, must be exactly the one discovery kept
26
+ * for this MCP server.
27
+ *
28
+ * `iss` only closes the class if the real third party actually sends `iss`,
29
+ * which nothing guarantees: most authorization servers deployed today do not
30
+ * implement RFC 9207. And `issParameterSupported` is itself read from the
31
+ * metadata of the authorization server the HOSTILE server designated — the
32
+ * attacker only has to OMIT the field for the guarantee never to arm, then
33
+ * aim at a genuine non-RFC-9207 third party. `state` does not cover that
34
+ * case either: the attacker's `authorization_endpoint` SEES our `state`
35
+ * before redirecting and can simply pass it along.
36
+ *
37
+ * There is therefore **no purely technical client-side check that closes this
38
+ * class when the AS does not emit `iss`** — which is precisely why RFC 9207
39
+ * exists. The decision is one of POLICY, taken in `connect.ts`: by default
40
+ * the flow warns and goes on when `issParameterSupported !== true` (RFC 9207
41
+ * is absent from nearly every public server measured, and the issuer is
42
+ * still the one discovery bound to the resource); `strictIssuer` — the
43
+ * `--strict-issuer` flag, or the organisation's policy (`strictIssuer`,
44
+ * served by the backend) — turns that into a refusal before any browser
45
+ * opens.
46
+ *
47
+ * Both checks live in this file, BEFORE the redirect promise resolves:
48
+ * `code` and `code_verifier` structurally CANNOT reach the exchange until
49
+ * they have passed. It is not a question of call order in the caller — the
50
+ * code does not exist anywhere else before that.
51
+ *
52
+ * Moved from `682d413:src/mcp/login.ts:194-396` and translated.
53
+ */
54
+ import { createServer } from 'node:http';
55
+ /**
56
+ * Raised by the loopback callback server. Never a free-form string: a closed
57
+ * `kind`, so the caller can tell `issuer-mismatch` — the heart of the RFC
58
+ * 9207 defence — from the rest without parsing a message.
59
+ */
60
+ export class AuthorizationRedirectError extends Error {
61
+ kind;
62
+ constructor(kind, message) {
63
+ super(message);
64
+ this.kind = kind;
65
+ this.name = 'AuthorizationRedirectError';
66
+ }
67
+ }
68
+ const CALLBACK_PATH = '/mcp-oauth-callback';
69
+ /**
70
+ * Strips one or more trailing slashes. RFC 9207 and RFC 8414 both tolerate an
71
+ * issuer with or without a trailing `/` (the same normalisation `issuerId`
72
+ * applies in `discovery.ts`), and conforming third parties — Auth0 among
73
+ * others — commonly emit one. The CASE is left alone: RFC 9207 §2.4 mandates
74
+ * simple string comparison.
75
+ */
76
+ function stripTrailingSlash(value) {
77
+ return value.replace(/\/+$/, '');
78
+ }
79
+ const SUCCESS_PAGE = '<!DOCTYPE html><html><head><meta charset="utf-8"><title>VibeDefend</title></head>' +
80
+ '<body style="font-family: system-ui, sans-serif; padding: 3rem; text-align: center">' +
81
+ '<h1>Authentication successful</h1>' +
82
+ '<p>VibeDefend has the token for this MCP server. You can close this tab.</p>' +
83
+ '</body></html>';
84
+ /**
85
+ * The real implementation: a loopback HTTP server (127.0.0.1 only, never
86
+ * 0.0.0.0) on a port the OS assigns. RFC 8252 recommends a random port for a
87
+ * native client, and `registerMcpClient` registers THIS exact `redirect_uri`
88
+ * dynamically, so no fixed port is needed — unlike `vibedefend login`, which
89
+ * targets a client pre-registered with Logto.
90
+ *
91
+ * Single use: once the response has been consumed, any further request — even
92
+ * with the right `state` — is refused rather than replayed.
93
+ */
94
+ export async function startMcpAuthorizationCallbackServer(expectedState, expectedIssuer, issParameterRequired, options = {}) {
95
+ let settled = false;
96
+ let resolveRedirect;
97
+ let rejectRedirect;
98
+ const redirectPromise = new Promise((res, rej) => {
99
+ resolveRedirect = res;
100
+ rejectRedirect = rej;
101
+ });
102
+ const server = createServer((req, res) => {
103
+ const url = new URL(req.url ?? '/', 'http://127.0.0.1');
104
+ if (url.pathname !== CALLBACK_PATH) {
105
+ res.writeHead(404).end();
106
+ return;
107
+ }
108
+ if (settled) {
109
+ res
110
+ .writeHead(400, { 'Content-Type': 'text/plain' })
111
+ .end('This authorization response was already used.');
112
+ return;
113
+ }
114
+ // 1) `state` — anti-CSRF, single use. Checked BEFORE `error`: RFC 6749
115
+ // §4.1.2.1 requires `state` on an error response too, and a hostile MCP
116
+ // server could otherwise pass an anonymous `?error=access_denied` off as
117
+ // an EXPLICIT refusal by the user.
118
+ //
119
+ // What this ordering is NOT: protection against a third party denying a
120
+ // login in progress. Any page open in the browser that knows the port —
121
+ // and the port is in `redirect_uri` — burns the attempt identically with
122
+ // or without it; only the LABEL changes, and the real callback that
123
+ // follows gets a 400 "already used" either way. Continuing to listen
124
+ // after a suspicious request would widen the window rather than close it:
125
+ // an unknown `state` on this ephemeral port is already either a mistake
126
+ // or a probe, never something to give a second chance. What the ordering
127
+ // does buy is a CORRECT diagnosis (`state-mismatch`, not `denied`) when
128
+ // the request that burned the attempt never knew the state.
129
+ const state = url.searchParams.get('state');
130
+ if (!state || state !== expectedState) {
131
+ settled = true;
132
+ res.writeHead(400, { 'Content-Type': 'text/plain' }).end('Invalid or already-consumed state.');
133
+ rejectRedirect(new AuthorizationRedirectError('state-mismatch', 'authorization response carried an unknown or already-consumed state'));
134
+ return;
135
+ }
136
+ const error = url.searchParams.get('error');
137
+ if (error) {
138
+ settled = true;
139
+ res.writeHead(400, { 'Content-Type': 'text/plain' }).end('Authorization was not granted.');
140
+ rejectRedirect(new AuthorizationRedirectError('denied', 'the user denied authorization, or the authorization server refused'));
141
+ return;
142
+ }
143
+ // 2) `iss` (RFC 9207) — see the module header. An `iss` that is PRESENT
144
+ // and does not match is ALWAYS a rejection; an `iss` that is ABSENT is
145
+ // one only when the AS announced it would always send one. Compared on
146
+ // the NORMALISED form: a CONFORMING RFC 9207 issuer ending in `/` (the
147
+ // Auth0 pattern, `https://tenant.eu.auth0.com/`) was refused by an exact
148
+ // comparison, reproducing on this axis the flaw that condemned the origin
149
+ // check — refusing conforming deployments. The CASE stays compared as is:
150
+ // RFC 9207 §2.4 mandates simple string comparison, and `issuerId` in
151
+ // `discovery.ts` does not normalise it either.
152
+ const iss = url.searchParams.get('iss');
153
+ if (iss !== null) {
154
+ if (stripTrailingSlash(iss) !== stripTrailingSlash(expectedIssuer)) {
155
+ settled = true;
156
+ res.writeHead(400, { 'Content-Type': 'text/plain' }).end('Issuer mismatch.');
157
+ rejectRedirect(new AuthorizationRedirectError('issuer-mismatch', 'authorization response `iss` does not match the issuer discovered for this MCP server'));
158
+ return;
159
+ }
160
+ }
161
+ else if (issParameterRequired) {
162
+ settled = true;
163
+ res
164
+ .writeHead(400, { 'Content-Type': 'text/plain' })
165
+ .end('Missing required issuer parameter.');
166
+ rejectRedirect(new AuthorizationRedirectError('issuer-mismatch', 'authorization server declares RFC 9207 support but the response is missing `iss`'));
167
+ return;
168
+ }
169
+ const code = url.searchParams.get('code');
170
+ if (!code) {
171
+ settled = true;
172
+ res.writeHead(400, { 'Content-Type': 'text/plain' }).end('Missing authorization code.');
173
+ rejectRedirect(new AuthorizationRedirectError('missing-code', 'authorization response is missing the authorization code'));
174
+ return;
175
+ }
176
+ settled = true;
177
+ res.writeHead(200, { 'Content-Type': 'text/html' }).end(SUCCESS_PAGE);
178
+ resolveRedirect({ code, iss });
179
+ });
180
+ const port = options.port ?? 0;
181
+ await new Promise((resolve, reject) => {
182
+ server.once('error', (error) => {
183
+ reject(port === 0
184
+ ? error
185
+ : new Error(`cannot listen on 127.0.0.1:${port} for the authorization callback: ${error.message}`));
186
+ });
187
+ server.listen(port, '127.0.0.1', resolve);
188
+ });
189
+ const addr = server.address();
190
+ const stop = () => new Promise((resolve) => {
191
+ server.closeAllConnections?.();
192
+ server.close(() => resolve());
193
+ });
194
+ return { port: addr.port, redirectPromise, stop };
195
+ }
196
+ /** The `redirect_uri` for a callback server listening on `port`. */
197
+ export function callbackRedirectUri(port) {
198
+ return `http://127.0.0.1:${port}${CALLBACK_PATH}`;
199
+ }
200
+ //# sourceMappingURL=callback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callback.js","sourceRoot":"","sources":["../../../src/mcp/auth/callback.ts"],"names":[],"mappings":"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"}