Summary
Severity: P1/High (Score: 75/150)
CWE: CWE-400 - Uncontrolled Resource Consumption
OWASP: A05:2021 - Security Misconfiguration
File: extensions/tlon/src/urbit/sse-client.ts
The Tlon extension's SSE client makes fetch requests without timeout or AbortSignal, causing connections to hang indefinitely if the Urbit server becomes unresponsive.
Why this is P1: Network partitions or server hangs cause permanent connection hangs, preventing auto-reconnect and causing resource leaks that accumulate over time.
Triage Assessment
| Factor |
Value |
Score |
| Reachability |
Any Tlon extension user with network issues |
20/40 |
| Impact |
Connection exhaustion, unresponsive extension |
25/50 |
| Exploitability |
Network partition or unresponsive server |
15/30 |
| Verification |
file:line ✓, code ✓, attack steps ✓ |
15/30 |
| Total |
— |
75/150 |
Steps to reproduce
- Connect to an Urbit server via the Tlon extension
- Simulate network partition or server hang (e.g., firewall drop)
- The SSE client fetch calls wait indefinitely
- Auto-reconnect logic cannot trigger because initial fetch never returns
Expected behavior
All network requests should have timeouts. Use AbortSignal.timeout() or similar to bound wait times.
Actual behavior
8 fetch call locations have no timeout mechanism. Network issues cause permanent hangs.
Affected code locations:
File (extensions/tlon/src/urbit/sse-client.ts):
- Line 110:
fetch() in sendSubscription() - no timeout
- Line 126:
fetch() in connect() - no timeout
- Line 139:
fetch() in connect() - no timeout
- Line 167:
fetch() in openStream() - no timeout
- Line 263:
fetch() in poke() - no timeout
- Line 282:
fetch() in scry() - no timeout
- Line 348:
fetch() in close() - no timeout
- Line 357:
fetch() in close() - no timeout
// Line 167: No timeout, no abort signal
async openStream() {
const response = await fetch(this.channelUrl, {
method: "GET",
headers: {
Accept: "text/event-stream",
Cookie: this.cookie,
},
});
// If server never responds, this hangs forever
}
Environment
- Version: latest (main branch)
- OS: Any
- Install method: Any
Logs or screenshots
N/A - issue is in code logic
Impact
- Connection exhaustion: Hanging connections accumulate over time
- Unresponsive extension: Tlon features become unavailable
- Resource leak: Open sockets and memory not released
- No recovery: Auto-reconnect cannot trigger if fetch never returns
Recommended fix
- Add AbortSignal.timeout:
signal: AbortSignal.timeout(30000) to all fetch calls
- Use fetchWithGuard pattern: Adopt the guarded fetch pattern from other modules
- Implement proper cleanup: Ensure error handlers release resources
- Add connection health monitoring: Detect stale connections and force reconnect
- Consider fetch wrapper: Create a timeout-enabled fetch utility for the extension
Summary
Severity: P1/High (Score: 75/150)
CWE: CWE-400 - Uncontrolled Resource Consumption
OWASP: A05:2021 - Security Misconfiguration
File:
extensions/tlon/src/urbit/sse-client.tsThe Tlon extension's SSE client makes fetch requests without timeout or AbortSignal, causing connections to hang indefinitely if the Urbit server becomes unresponsive.
Why this is P1: Network partitions or server hangs cause permanent connection hangs, preventing auto-reconnect and causing resource leaks that accumulate over time.
Triage Assessment
Steps to reproduce
Expected behavior
All network requests should have timeouts. Use
AbortSignal.timeout()or similar to bound wait times.Actual behavior
8 fetch call locations have no timeout mechanism. Network issues cause permanent hangs.
Affected code locations:
File (
extensions/tlon/src/urbit/sse-client.ts):fetch()insendSubscription()- no timeoutfetch()inconnect()- no timeoutfetch()inconnect()- no timeoutfetch()inopenStream()- no timeoutfetch()inpoke()- no timeoutfetch()inscry()- no timeoutfetch()inclose()- no timeoutfetch()inclose()- no timeoutEnvironment
Logs or screenshots
N/A - issue is in code logic
Impact
Recommended fix
signal: AbortSignal.timeout(30000)to all fetch calls