Skip to content

[Fix] safeFetch redirect SSRF regression tests#524

Merged
samzong merged 1 commit into
clawwork-ai:mainfrom
advancedresearcharray:fix/406-safefetch-redirect-regression
Jun 6, 2026
Merged

[Fix] safeFetch redirect SSRF regression tests#524
samzong merged 1 commit into
clawwork-ai:mainfrom
advancedresearcharray:fix/406-safefetch-redirect-regression

Conversation

@advancedresearcharray

@advancedresearcharray advancedresearcharray commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Test plan

  • pnpm check passes
  • vitest run test/safe-fetch.test.ts — 19 tests pass

Closes #406

@github-actions

github-actions Bot commented Jun 6, 2026

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 introduces comprehensive regression tests for the safeFetch utility to ensure SSRF protection mechanisms are functioning as expected. By validating that redirect responses are correctly rejected and that errors are propagated, these tests reinforce the security fixes implemented in previous changes.

Highlights

  • Regression Testing: Added three new test cases to safe-fetch.test.ts to verify that safeFetch correctly handles and rejects 302 redirects.
  • Security Validation: Confirmed that redirects to private hosts (e.g., 127.0.0.1) and alternate HTTPS URLs are blocked without following the Location header.
  • Error Propagation: Verified that fetch errors resulting from redirect: 'error' are properly propagated instead of being silently ignored.
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 adds three new unit tests to safe-fetch.test.ts to verify redirect handling in safeFetch. The feedback correctly points out that two of these tests mock an unrealistic scenario where net.fetch resolves with a 302 status code despite being configured with redirect: 'error'. Since net.fetch would actually reject with a TypeError in practice, these tests are redundant and should be removed.

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.

Comment on lines +176 to +193
it('rejects redirect response pointing to private host without following Location', async () => {
assertNotPrivateHostMock.mockResolvedValue(null);
netFetchMock.mockResolvedValue(mockResponse(new ArrayBuffer(0), 302, { Location: 'http://127.0.0.1/admin' }));

await expect(safeFetch('https://cdn.example.com/img.png')).rejects.toThrow('302');
expect(assertNotPrivateHostMock).toHaveBeenCalledTimes(1);
expect(assertNotPrivateHostMock).toHaveBeenCalledWith('cdn.example.com');
});

it('rejects redirect response to another HTTPS URL without following Location', async () => {
assertNotPrivateHostMock.mockResolvedValue(null);
netFetchMock.mockResolvedValue(
mockResponse(new ArrayBuffer(0), 302, { Location: 'https://other.example.com/img.png' }),
);

await expect(safeFetch('https://cdn.example.com/img.png')).rejects.toThrow('302');
expect(assertNotPrivateHostMock).toHaveBeenCalledTimes(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.

medium

When redirect: 'error' is configured, net.fetch (like standard fetch) will reject the promise with a TypeError when encountering a redirect, rather than resolving with a 302 response.

By mocking netFetchMock.mockResolvedValue(...) with a 302 status, these tests simulate an impossible scenario where net.fetch resolves with a redirect response despite redirect: 'error' being set. In this simulated scenario, safeFetch only rejects because of the fallback if (!res.ok) check, which is already covered by the 'rejects on non-ok HTTP status' test.

Since the actual redirect-blocking behavior is already covered by:

  1. 'passes redirect:error to net.fetch to prevent SSRF bypass via 3xx' (verifying the option is passed)
  2. 'propagates fetch error when redirect:error blocks a 3xx before response' (verifying that the rejection propagates)

These two tests are redundant and mock an unrealistic behavior. They should be removed to avoid confusion.

Add behavioral tests confirming safeFetch rejects 3xx responses
pointing at private or alternate HTTPS hosts without following
Location, and propagates redirect:error fetch failures.

Closes clawwork-ai#406

Signed-off-by: root <root@array-fleet-ops.array.local>
@samzong

samzong commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

Thanks @advancedresearcharray!

/approve
/lgtm

@github-actions github-actions Bot added approved Approved for merge lgtm Looks good to me labels Jun 6, 2026
@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

@samzong

I encountered an error while processing your command:

❌ Failed to merge the PR. Please ensure all required checks have passed and there are no conflicts.

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.

@advancedresearcharray

Copy link
Copy Markdown
Contributor Author

Branch is mergeable again — the earlier /approve merge failure was transient. Ready for re-merge when convenient.

@samzong samzong merged commit 3fe0d19 into clawwork-ai:main Jun 6, 2026
11 checks passed
@advancedresearcharray

Copy link
Copy Markdown
Contributor Author

Thanks @samzong for the review and merge!

Re the Gemini review on the two 302 mock tests: they intentionally match the verification steps in #406 (reject a mocked 302 Location: http://127.0.0.1/admin and a 302 to another HTTPS URL). With redirect: 'error', real net.fetch rejects before a Response is returned — the 'propagates fetch error when redirect:error blocks a 3xx before response' test covers that path. The 302 mocks document the defense-in-depth !res.ok fallback if a redirect response ever surfaced. Happy to trim them in a follow-up if maintainers prefer leaner coverage.

@advancedresearcharray advancedresearcharray deleted the fix/406-safefetch-redirect-regression branch June 10, 2026 20:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Approved for merge lgtm Looks good to me

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] safeFetch follows redirects without re-running SSRF check

2 participants