Skip to content

fix: harden egress proxy error handling - #23

Merged
abnegate merged 2 commits into
mainfrom
cursor/egress-proxy-error-handling-1edf
Oct 22, 2026
Merged

abnegate merged 2 commits into
mainfrom
cursor/egress-proxy-error-handling-1edf

Conversation

@abnegate

Copy link
Copy Markdown
Member

The egress forward proxy forwarded upstream status lines and headers through res.writeHead with no error handling. Under Bun, the HTTP client parser accepts some status codes and reason phrases that the server-side writer then rejects (for example a status code below 100, or a non-ASCII reason phrase). That throw escaped the request callback and ended the process.

The same handlers await the host resolver. A rejected lookup became an unhandled rejection on both the plain-HTTP and CONNECT paths.

This change fails the affected connection instead: HTTP clients get 502 (or the socket is destroyed if headers were already sent), and CONNECT clients get 502 or a destroyed socket. An error listener is also attached to the upstream response stream.

Tests

Unit tests drive startEgressGuard through a local raw upstream and cover:

  • a normal 200 still forwards
  • a rejected status message or status code returns 502 without an uncaught exception
  • a rejected resolver returns 502 on HTTP and CONNECT
  • the guard still serves a later request after a rejected upstream response
  • CONNECT still tunnels to a reachable host and returns 502 when the destination refuses

Verified locally with Bun 1.3.2 (the Dockerfile version): bun run lint, bun run check, bun run type-check, and bun test tests/unit.

Open in Web Open in Cursor 

cursoragent and others added 2 commits October 22, 2026 20:29
Catch writeHead failures and rejected resolver promises on the HTTP and
CONNECT paths so a bad upstream response or lookup fails that connection
with 502 instead of leaving an unhandled exception.

Co-authored-by: Jake Barnby <[email protected]>
CI installs Bun latest, which accepts a UTF-8 reason phrase the
Dockerfile version rejects. Drive the writer-reject cases with a
control byte the client parser keeps and writeHead still refuses.

Co-authored-by: Jake Barnby <[email protected]>
@github-actions

Copy link
Copy Markdown

Docker Image Stats

Metric Value
Image Size 494MB
Memory Usage 158.2MiB
Cold Start Time 1.02s
Screenshot Time 1.61s

Screenshot benchmark: Average of 3 runs on https://appwrite.io

Copy link
Copy Markdown
Member Author

@hansi-codes review

@hansi-codes

hansi-codes Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

🟢 Tier S · Ready to merge

The egress proxy now converts resolver failures and rejected upstream HTTP responses into controlled gateway failures, and handles stream/socket errors without letting request-handler exceptions escape. Unit tests exercise HTTP forwarding, malformed upstream status values, resolver failures, continued service, and CONNECT tunneling and refusal cases.

Verdict New comments Fixed Still open
✅ Approved 0 0 0
📂 Walkthrough · 2
File Change
src/utils/egress.ts Adds guarded HTTP and CONNECT error handling, including fallback responses and upstream response stream error handling.
tests/unit/egress.test.ts Adds raw-socket unit coverage for normal forwarding, malformed upstream statuses, resolver failures, and CONNECT behavior.

Reviewed 267c7fb · Details · Comment @hansi-codes review to re-run, or mention @hansi-codes with a question.

@hansi-codes hansi-codes Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Tier S · Looks good to merge. Summary

@abnegate
abnegate marked this pull request as ready for review October 22, 2026 23:31
@abnegate
abnegate merged commit 3fee542 into main Oct 22, 2026
4 checks passed
@abnegate
abnegate deleted the cursor/egress-proxy-error-handling-1edf branch October 22, 2026 23:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants