Skip to content

fix: drain redirect response and resolve relative URLs in downloadFile#25375

Open
KevinZhao wants to merge 1 commit intogoogle-gemini:mainfrom
KevinZhao:fix/downloadfile-redirect-drain
Open

fix: drain redirect response and resolve relative URLs in downloadFile#25375
KevinZhao wants to merge 1 commit intogoogle-gemini:mainfrom
KevinZhao:fix/downloadfile-redirect-drain

Conversation

@KevinZhao
Copy link
Copy Markdown
Contributor

Follow-up to #24896 — applies the same two fixes to the sibling function downloadFile in github.ts.

Problem

downloadFile has the same redirect handling issues that were fixed in fetchJson (#24896):

  1. Socket leak: The redirect response body is not consumed. Node.js keeps the underlying TCP socket open until the response stream is drained or garbage collected, which can cause socket exhaustion under repeated redirects.

  2. Relative redirect URLs: res.headers.location is passed directly to the recursive call without resolving against the current URL. Relative Location headers (e.g. /path/to/file) would fail since https.get expects an absolute URL.

Changes

  • Add res.resume() before following redirect to drain the response body and release the socket
  • Use new URL(res.headers.location, url).toString() to resolve relative Location headers against the current URL

Both fixes mirror the approach already applied to fetchJson in #24896.

Test plan

The `downloadFile` function in `github.ts` has the same two issues that
were fixed in `fetchJson` (google-gemini#24896):

1. The redirect response body is not consumed, which can cause socket
   exhaustion under repeated redirects (Node.js keeps the socket open
   until the response is drained or garbage collected).

2. `res.headers.location` is passed directly to the recursive call
   without resolving against the current URL. Relative `Location`
   headers (e.g. `/path/to/file`) would fail with `ERR_INVALID_URL`
   since `https.get` expects an absolute URL.

Both fixes mirror the approach already applied to `fetchJson`.
@KevinZhao KevinZhao requested a review from a team as a code owner April 14, 2026 10:32
@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 two critical issues in the downloadFile function within github.ts, ensuring consistent behavior with previously applied fixes in fetchJson. By properly draining response streams and resolving relative redirect URLs, the changes improve network resource management and reliability when handling redirected download requests.

Highlights

  • Socket Management: Added res.resume() to the redirect handling logic to properly drain the response body and prevent socket exhaustion.
  • URL Resolution: Implemented URL resolution using the URL constructor to correctly handle relative Location headers during redirects.
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 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 counter productive. 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-cli gemini-cli Bot added priority/p3 Backlog - a good idea but not currently a priority. area/extensions Issues related to Gemini CLI extensions capability help wanted We will accept PRs from all issues marked as "help wanted". Thanks for your support! labels Apr 14, 2026
Copy link
Copy Markdown
Contributor

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

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 updates the downloadFile function in the GitHub extension to properly drain response bodies using res.resume() during redirects and to correctly resolve redirect URLs. Review feedback identifies missing resource cleanup in error paths that could lead to socket leaks and a high-severity security risk where the Authorization header might be leaked to untrusted domains during redirects.

);
}
downloadFile(res.headers.location, dest, options, redirectCount + 1)
res.resume(); // Drain response body to free the socket
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.

high

While adding res.resume() here is correct, the same logic is missing in the error paths within this redirect block. Specifically, if the redirect count is exceeded (line 538) or if the Location header is missing (line 542), the response body is not drained, leading to a socket leak. To ensure robust resource management, the response should be resumed in all cases where the body is not consumed.

downloadFile(res.headers.location, dest, options, redirectCount + 1)
res.resume(); // Drain response body to free the socket
const redirectUrl = new URL(res.headers.location, url).toString();
downloadFile(redirectUrl, dest, options, redirectCount + 1)
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.

security-high high

Following redirects blindly while re-adding the Authorization header poses a security risk. If the request is redirected to a different domain (e.g., a CDN like S3 where GitHub release assets are often stored), the GitHub token will be leaked to that third party. According to GitHub's security best practices, the Authorization header should only be sent to trusted GitHub domains (e.g., github.com or api.github.com) and should be stripped when following redirects to external hosts. The implementation should be updated to only include the Authorization header if the target URL is on a trusted domain. Note that since the token is added at the start of the downloadFile function (lines 528-531), the fix should be applied there. This same issue likely exists in the fetchJson function in github_fetch.ts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/extensions Issues related to Gemini CLI extensions capability help wanted We will accept PRs from all issues marked as "help wanted". Thanks for your support! priority/p3 Backlog - a good idea but not currently a priority.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant