Skip to content

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

@samzong

Description

@samzong

Problem

safeFetch calls net.fetch(url, { signal }) without setting redirect. Electron's net.fetch follows HTTP redirects (3xx responses) by default, and the SSRF guard only runs once against the initial URL. A public-facing HTTPS endpoint controlled by an attacker can respond with 302 Location: http://127.0.0.1/admin (or any internal host), and the second request goes through completely unchecked — the guard is bypassed. Protocol downgrade (HTTPS → HTTP) is also allowed for the same reason.

Location

File: packages/desktop/src/main/net/safe-fetch.ts:12-27

export async function safeFetch(url: string, opts: SafeFetchOptions = {}): Promise<Buffer> {
  const parsed = new URL(url);
  if (parsed.protocol !== 'https:') throw new Error('HTTPS required');
  await assertNotPrivateHost(parsed.hostname);
  // ...
  const res = await net.fetch(url, { signal: controller.signal });  // ← follows redirects blindly

Fix Approach

Pick one of:

  1. Preferred: pass redirect: 'error' to net.fetch so any 3xx response throws. This is the simplest and safest option; image URLs generally should not redirect through untrusted hops.
  2. If redirects must be supported: pass redirect: 'manual', inspect the Location header, validate the new URL against the HTTPS-only check AND assertNotPrivateHost, then re-issue the fetch. Bound the redirect chain to a small maximum (e.g. 3 hops) to prevent redirect loops.

Verification

  1. Run pnpm check — must pass.
  2. Unit test: mock net.fetch to return a 302 Location: http://127.0.0.1/ response; confirm safeFetch rejects.
  3. Unit test: mock a 302 → public HTTPS redirect; confirm it either rejects (option 1) or re-validates (option 2).

Context

  • WG: Observability & DX (security-critical)
  • Priority: Medium (same attack surface as the DNS rebinding bug)
  • Estimated effort: 30-60 minutes

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/dxObservability & DX WGhelp wantedExtra attention is neededkind/bugCategorizes issue or PR as related to a bugsecuritySecurity related issues

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions