Commit 922515f
authored
fix(mcp): bound OAuth discovery/DCR/token fetches with a timeout (#5776)
* fix(mcp): bound OAuth discovery/DCR/token fetches with a timeout
The MCP SDK issues OAuth discovery, dynamic client registration, and token
exchange with a bare fetch and no AbortSignal (only the JSON-RPC layer gets the
SDK's request timeout), and undici's default headers/body timeouts are 5 min. A
slow or unresponsive authorization server therefore left /oauth/start pending for
minutes — the browser stuck on "Connecting…" forever.
Bound each guarded OAuth/revocation leg with a 30s AbortSignal.timeout, composed
with any caller signal so cancellation still works. Only our own deadline is
relabeled to an McpError; caller aborts and other failures propagate unchanged.
Scoped to createSsrfGuardedMcpFetch (OAuth/revoke/probe) — the live transport's
timeouts are untouched.
* fix(mcp): bound SSRF/DNS validation by the deadline too
Move the timeout signal ahead of validateMcpServerSsrf and race the validation
(whose dns.lookup takes no signal) against it, so the deadline covers the whole
guarded call — a stalled DNS resolution now rejects at timeoutMs instead of the
OS DNS timeout. Listener is cleaned up on settle so a late timeout can't surface
as an unhandled rejection.
* fix(mcp): compose caller signal before validation + attribute timeout by reason
Compose the caller's AbortSignal with the deadline up front and use the combined
signal for both SSRF validation and the HTTP request, so caller cancellation now
covers the whole guarded call (previously a caller abort during a stalled DNS
validation waited for the full deadline). Attribute the timeout relabel by the
rejection reason's identity rather than init.signal's state, so a caller signal
that aborts just after the deadline can't misattribute a genuine timeout.
* fix(mcp): adopt in-flight validation on early abort to avoid unhandled rejection
When raceWithSignal is entered with an already-aborted signal it returned without
attaching to the in-flight validateMcpServerSsrf promise, so a later SSRF/DNS
rejection could surface as an unhandled rejection. Swallow the orphaned promise's
settlement in the early-abort branch.
* test(mcp): use sleep() instead of raw setTimeout in pinned-fetch test
check:utils bans new Promise(resolve => setTimeout(...)) in favor of sleep() from
@sim/utils/helpers.1 parent 6e5356b commit 922515f
2 files changed
Lines changed: 172 additions & 12 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
32 | 33 | | |
33 | 34 | | |
34 | 35 | | |
35 | | - | |
36 | | - | |
37 | | - | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
38 | 131 | | |
39 | 132 | | |
40 | 133 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
31 | 32 | | |
32 | 33 | | |
33 | 34 | | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
34 | 78 | | |
35 | 79 | | |
36 | 80 | | |
| |||
42 | 86 | | |
43 | 87 | | |
44 | 88 | | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
50 | 100 | | |
| 101 | + | |
51 | 102 | | |
| 103 | + | |
52 | 104 | | |
53 | | - | |
| 105 | + | |
54 | 106 | | |
55 | 107 | | |
56 | | - | |
57 | | - | |
58 | | - | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
59 | 126 | | |
60 | 127 | | |
0 commit comments