[Bug] Severe TCP Socket Leak / Zombie Connections Causing Enterprise Firewall Exhaustion (20k+ Sessions)

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Cursor appears to have a severe connection lifecycle management issue, resulting in massive TCP socket leaks (Zombie Connections). In an enterprise environment, this behavior exhausts the stateful firewall’s session tables (e.g., Sangfor AC), generating over 20,000 ESTABLISHED sessions from a single client IP within a few days.

Steps to Reproduce

Launch Cursor and actively use AI features (e.g., Copilot++, Chat, or Codebase Indexing) to establish multiple HTTPS connections to *.cursor.sh endpoints.

Simulate a sudden network disruption or state change. You can do this by abruptly toggling the Wi-Fi off and on, or by forcing the macOS to sleep and immediately waking it up.

Run a network capture tool (e.g., sudo tcpdump -i en0 -nn ‘tcp port 443’) or monitor the sockets via nettop.

Observe the abandoned TCP streams. You will notice that Cursor’s underlying Node.js/Electron network module fails to catch the exception or timeout.

Crucial observation: The application never issues a [FIN] or [RST] packet to tear down the dead socket. Instead, the socket leaks and is kept artificially alive purely by OS-level [TCP Keep-Alive] probes, remaining stuck in the ESTABLISHED state indefinitely.

Expected Behavior

Graceful Teardown: When a network request times out, fails due to jitter, or when the underlying microservice panics, Cursor’s network client must explicitly invoke socket.close() or .destroy() to ensure the OS sends a [FIN] or [RST] packet to the server.

Timeout Handling: The application should implement strict application-level timeouts for its API calls, rather than relying indefinitely on the OS’s TCP stack.

Firewall Friendly: Dead connections should not be left hanging. Properly tearing down dead sockets prevents “Zombie Connections” from accumulating and exhausting the session tables of enterprise stateful firewalls (which often hold ESTABLISHED connections for hours or days).

Operating System

MacOS

Version Information

Version: 3.1.15
VSCode Version: 1.105.1
Commit: 3a67af7b780e0bfc8d32aefa96b8ff1cb8817f80
Date: 2026-04-15T01:46:06.515Z
Layout: editor
Build Type: Stable
Release Track: Default
Electron: 39.8.1
Chromium: 142.0.7444.265
Node.js: 22.22.1
V8: 14.2.231.22-electron.0
OS: Darwin arm64 25.4.0

For AI issues: which model did you use?

N/A - Transport Layer Issue. > This is an underlying network module defect (TCP socket leak) in the Electron/Node.js client, independent of the specific AI model. However, the connection bursts were frequently observed while using Claude 3.5 Sonnet and Cursor Tab.

For AI issues: add Request ID with privacy disabled

N/a

Additional Information

N/A. > This is a cumulative connection lifecycle issue (missing FIN/RST packets), not an error with a specific AI generation request. Therefore, a single Request ID is not applicable. Please refer to the attached PCAP files and Wireshark screenshots for network-level evidence of the zombie connections.

Does this stop you from using Cursor

No - Cursor works, but with this issue

验证cursor+未正常关闭TCP连接导致会话数爆炸_1_10_translate_20260421192307.pdf (5.4 MB)

Hey, thanks for the detailed report. We rarely get ones with code analysis, tcpdump, and Wireshark, and it really helps.

I can confirm the behavior you described. During network transitions like sleep and wake, or toggling Wi-Fi, the client intentionally doesn’t abort the HTTP/2 session managers. They get removed from the tracking set, but the underlying TCP sockets only close on idle timeout or ping failure. With a stateful firewall like Sangfor AC, this can lead to a buildup of ESTABLISHED sessions. This is an architectural detail of the client networking layer, not a mis-report.

I’ve reported this internally to the team. I can’t share an ETA for a fix yet, but I’ll post an update in the thread when I have one.

As a workaround to reduce the buildup, you can try disabling HTTP/2 on the client: Settings Cmd+, > search for HTTP/2 > turn on Disable HTTP/2. With HTTP/1.1 the connection lifecycle is cleaner, the agents get properly destroyed in destroyAllAgents(), and it should noticeably reduce zombie sessions in your environment. I’d be interested to hear if this improves your firewall metrics.

I’d like to continue reporting this issue: the Cursor process consumes a significant amount of bandwidth even when idle. As shown in the screenshot, the heartbeat traffic from the idle Cursor process is very large (100 KB+). Note that I haven’t loaded any large projects; I simply opened the Cursor app. Why is this happening? It’s truly a waste of bandwidth.
The attached screenshot shows that even when the computer is locked, large traffic requests are still initiated at 20-minute intervals.

How can I disable or reduce the heartbeat packet traffic?

Thanks for the screenshot. A 20-minute interval and about 100 KB per burst doesn’t match the excessive polling pattern we’re tracking in 3.1.15. That issue looks different, with hundreds of requests per minute, not one burst every 20 minutes. What you’re seeing is most likely normal periodic activity spread across three hosts:

  • api2.cursor.sh - general API calls like auth refresh, feature flags, telemetry batch
  • api3.cursor.sh - the HTTP/2 endpoint for chat and agent
  • repo42.cursor.sh - codebase indexing sync

One more important thing. Seeing repo42.cursor.sh in the list usually means you have a workspace open with indexing enabled, even if the project isn’t big. Indexing syncs with the backend periodically even if you’re not doing anything in the IDE.

To figure out if this is baseline or a real anomaly, I’d need:

  1. When you took the screenshot, did you have any workspace or folder open, or was the Cursor window empty with no folder open?
  2. In Cursor Settings (not VS Code settings) > Indexing & Docs, is codebase indexing enabled? If yes and you don’t need it for this project, you can turn it off there. Traffic to repo42.cursor.sh should go away.
  3. If you can, what’s the total traffic per hour across these spikes? The app in your screenshot should show a per-host breakdown. 100 KB x 3 times per hour is about 300 KB per hour, which is basically a near-zero baseline for an IDE. If it’s much higher, that’s more interesting.

The TCP socket leak you mentioned in your original post is a separate issue. It’s already reported internally, but there’s no ETA yet. We can look at this idle traffic separately once you answer the questions above.

I am preparing the data and screenshots you mentioned; please wait a moment. By the way, I noticed there are also requests to the domain api4.cursor.sh. What is the purpose of this domain?

There are two traffic anomalies in cursor:

  1. The bandwidth of the quiet state is 5-8KB most of the time, and there is almost no traffic compared to the quiet state of claude desktop

  2. There is a large bandwidth every 20 minutes or so, which is about 100KB+

Assuming a maximum peak of 100KB, if a company has 3000 clients at the same time, the resulting bandwidth is very large.

Theoretical total bandwidth = 100KB x 8 x 3000 = 240Mbit (bandwidth)

My company has encountered this problem, which has caused a lot of waste of our company’s export bandwidth, I hope you can follow Claude CodeThere are two traffic anomalies in cursor:

20260422122920_Cursor主要域名流量用途研究测试_1_3_translate.docx (1.0 MB)

Thanks for the screenshots. A few things I want to call out before we draw conclusions:

About 395 KB sent / 115 KB received: in the Little Snitch screenshot it’s not clear what time period that total covers. Over an hour, that’s noticeable. Over a day, that’s basically baseline. Can you confirm the measurement interval?

No workspace does not mean fully idle. On the welcome screen, Cursor still does things in the background like:

  • fetching metadata for recent projects
  • auth session refresh, feature flags, update check
  • Cursor Tab model warmup
  • Your Cursor Settings (not VS Code settings) > Indexing & Docs shows Loading…, which means the indexing service is actively calling the backend even with no project open

The comparison with Claude Desktop isn’t totally fair. It’s a chat client with minimal functionality, while Cursor is a full IDE with telemetry, auth, feature flags, model pre-warm, etc. Also in your screenshot Claude isn’t in a clean idle state either since it says Downloading update at the bottom.

What actually matters for debugging is the number of requests, not the KB amount. The regression we’re tracking on Windows is measured in hits like 62K to 111K HTTP 200 to api2.cursor.sh over a period. In Little Snitch, you can open the right sidebar for a specific domain and check Connections count for the last hour. If that’s tens of thousands of requests, that’s definitely our case and I’ll pass it to the team. If it’s hundreds to a few thousand, it’s more likely expected baseline for an IDE.

Also, I see api3.cursor.sh with a red X in Little Snitch. Is it blocked? That can skew the picture since some traffic will shift to other endpoints.