Skip to content

Fix: DNS rebinding TOCTOU in safeFetch (#405)#538

Open
advancedresearcharray wants to merge 3 commits into
clawwork-ai:mainfrom
advancedresearcharray:fix/405-safe-fetch-dns-rebinding-toctou
Open

Fix: DNS rebinding TOCTOU in safeFetch (#405)#538
advancedresearcharray wants to merge 3 commits into
clawwork-ai:mainfrom
advancedresearcharray:fix/405-safe-fetch-dns-rebinding-toctou

Conversation

@advancedresearcharray

@advancedresearcharray advancedresearcharray commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #405.

  • assertNotPrivateHost: throw SSRF blocked: DNS resolution failed when hostname DNS lookup fails or returns no addresses, instead of returning null and letting net.fetch re-resolve independently (DNS rebinding TOCTOU).
  • safeFetch: fire-and-forget reader.cancel() when streaming past maxSize so a slow cancel cannot delay the error.
  • Tests: regression coverage for DNS failure, empty lookup results, exact maxSize bodies, and bounded streaming.

Root cause

When the SSRF guard DNS lookup failed or returned no addresses, assertNotPrivateHost returned null. safeFetch then called net.fetch with the original hostname, which performs its own DNS resolution — reopening the TOCTOU window between the guard check and the actual fetch.

Test plan

  • vitest run test/ssrf-guard.test.ts test/safe-fetch.test.ts — 97 tests pass

@github-actions

Copy link
Copy Markdown
Contributor

Hi @advancedresearcharray,
Thanks for your pull request!
If the PR is ready, use the /auto-cc command to assign Reviewer to Review.
We will review it shortly.

Details

Instructions for interacting with me using comments are available here.
If you have questions or suggestions related to my behavior, please file an issue against the gh-ci-bot repository.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a security vulnerability related to DNS rebinding in the safeFetch utility. By ensuring that DNS resolution results are strictly enforced and preventing re-resolution by the underlying fetch implementation, the change closes a Time-of-Check to Time-of-Use (TOCTOU) window. Additionally, it enhances resource management by ensuring that streams are properly cancelled and aborted when they exceed defined size limits.

Highlights

  • DNS Rebinding Mitigation: Updated assertNotPrivateHost to throw an error instead of returning null when DNS resolution fails or returns no addresses, preventing the net.fetch call from re-resolving the hostname and opening a TOCTOU window.
  • IPv6 Formatting: Added formatPinnedHostname to correctly wrap IPv6 addresses in brackets when rewriting URLs for pinned DNS.
  • Streaming Resource Management: Improved safeFetch to cancel the response body reader and abort the fetch signal immediately when the response size exceeds the configured limit, preventing unnecessary data consumption.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request enhances SSRF protection and stream handling in safe-fetch.ts and ssrf-guard.ts. Specifically, it correctly formats pinned IPv6 hostnames with brackets, throws an error when DNS resolution fails to prevent TOCTOU vulnerabilities, and cancels the stream reader when the response size exceeds maxSize. The feedback suggests avoiding awaiting reader.cancel() to prevent blocking or delaying the 'response too large' error.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

if (done) break;
total += value.byteLength;
if (total > maxSize) {
await reader.cancel().catch(() => undefined);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Awaiting reader.cancel() here can block the execution and delay throwing the 'response too large' error (or even hang indefinitely if the stream's cancel promise hangs). Since we are already aborting the controller and throwing an error, we can trigger the cancellation in the background without awaiting it.

Suggested change
await reader.cancel().catch(() => undefined);
reader.cancel().catch(() => undefined);

@advancedresearcharray

Copy link
Copy Markdown
Contributor Author

Addressed review feedback in 361dd9c: reader.cancel() is now fire-and-forget (not awaited) when rejecting oversized streams, so a slow/hanging cancel cannot delay the `response too large` error.

Verified locally: `vitest run test/ssrf-guard.test.ts test/safe-fetch.test.ts` — 97 tests pass.

advancedresearcharray and others added 2 commits June 15, 2026 05:53
Do not await reader.cancel() when rejecting oversized streams; abort
the fetch and throw immediately so a slow cancel cannot delay the error.

Add regression test for bodies exactly at maxSize.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ai#405)

Tighten SSRF guard regression tests to match the thrown error string
when hostname lookup fails or returns no addresses.

Co-authored-by: Cursor <cursoragent@cursor.com>
@advancedresearcharray advancedresearcharray force-pushed the fix/405-safe-fetch-dns-rebinding-toctou branch from 352d638 to e9fdb0c Compare June 15, 2026 14:54
@advancedresearcharray

Copy link
Copy Markdown
Contributor Author

This PR is ready for merge. CI is green, and there are no outstanding review comments.

@advancedresearcharray

Copy link
Copy Markdown
Contributor Author

This PR is ready to be merged! 🚀

Please review and merge when convenient. 😊

@advancedresearcharray

Copy link
Copy Markdown
Contributor Author

DNS rebinding TOCTOU fix is ready to merge. CI is green, and no further action required.

@advancedresearcharray

Copy link
Copy Markdown
Contributor Author

PR looks good! Ready for merge.

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.

[Bug] safeFetch is vulnerable to DNS rebinding TOCTOU (SSRF bypass)

1 participant