Skip to content

fix(security): SSRF guard checks resolved addresses, pins connection (v0.12.299) - #506

Merged
VickyXAI merged 2 commits into
mainfrom
fix/ssrf-dns-resolve
Oct 22, 2026
Merged

VickyXAI merged 2 commits into
mainfrom
fix/ssrf-dns-resolve

Conversation

@VickyXAI

@VickyXAI VickyXAI commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

img2img image/mask URL downloads: ssrfSafeFetch checked only the literal hostname, so public names resolving to private addresses (localtest.me, 127.0.0.1.nip.io, 169.254.169.254.nip.io) passed, and fetch() re-resolved to connect (DNS-rebinding window). Reported externally.

  • Each hop (redirects included) resolves the host and refuses if any address is loopback/private/link-local/CGNAT/metadata.
  • The connection is pinned to the vetted addresses via a lookup override on node:http(s) — no second resolution. Host/SNI/cert still use the hostname. No undici dependency (undici 8 does not load on Node < 22.15).
  • With an upstream proxy configured, requests still go through it (resolve-time check only, since the proxy resolves).
  • CLAWROUTER_ALLOW_PRIVATE_FETCH=1 unchanged.

Verified live: localtest.me and 127.0.0.1.nip.io are refused; public HTTPS through a redirect still returns 200. Release bump to 0.12.299 included.

Summary by CodeRabbit

  • Bug Fixes
    • Improved protection when fetching images from URLs: each redirect is checked, and direct connections use only verified public addresses.
    • Requests routed through an upstream proxy continue to use the proxy for name resolution.
  • Release
    • Updated the application to version 0.12.299.

1bcMax added 2 commits October 22, 2026 14:07
…he connection

isBlockedSsrfHost() checked the hostname as written, so public names that
resolve to private addresses (localtest.me, 127.0.0.1.nip.io,
169.254.169.254.nip.io) passed, and fetch() re-resolved the name to connect,
leaving a DNS-rebinding window. Each hop now resolves the host, refuses if any
address is blocked, and connects only to the vetted addresses. Behind an
upstream proxy the request still goes through it, with the resolve-time check.
@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between 493390c and d0fd906.

⛔ Files ignored due to path filters: 1
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing: 6
  • CHANGELOG.md
  • apps/desktop/electron/core/runtime.ts
  • package.json
  • src/local-guard.test.ts
  • src/local-guard.ts
  • src/proxy.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

📝 Walkthrough

The change adds resolved-address checks and pinned direct connections to img2img URL fetching. Redirect targets are checked on each hop. The img2img handler passes upstream proxy configuration to the fetch logic. The package version and changelog are updated.

Changes: SSRF-safe image URL fetching

Layer / File(s) Summary
Resolved-address validation and pinned transport
src/local-guard.ts, src/local-guard.test.ts
The guard resolves hostnames and rejects blocked or empty address results. Direct HTTP(S) requests use validated addresses. Tests cover resolution, lookup, and pinned request behavior.
Redirect checks and proxy routing
src/local-guard.ts, src/proxy.ts, src/local-guard.test.ts, CHANGELOG.md, package.json, apps/desktop/electron/core/runtime.ts
ssrfSafeFetch checks addresses on each redirect hop and uses pinned requests unless an upstream proxy is configured. The img2img handler passes the proxy setting. The changelog and package versions are updated.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~30 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant Img2imgHandler
  participant SsrfSafeFetch
  participant DNSResolver
  participant PinnedFetch
  participant UpstreamProxy
  Img2imgHandler->>SsrfSafeFetch: Pass image URL and proxy setting
  SsrfSafeFetch->>DNSResolver: Resolve and validate redirect hostname
  alt No upstream proxy
    SsrfSafeFetch->>PinnedFetch: Request using validated addresses
  else Upstream proxy configured
    SsrfSafeFetch->>UpstreamProxy: Fetch URL through proxy
  end
Loading

Suggested reviewers: killerqueen-z

Merge Risk: 🔵 Low · up to d0fd9

Img2img URL downloads may fail in proxy-only-DNS deployments. This is a bounded compatibility risk to acknowledge before merging.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 4 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main security change: checking resolved addresses and pinning connections to strengthen SSRF protection. The version identifier is also consistent with th…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title clearly and concisely describes the main security change: checking resolved addresses and pinning connections to strengthen SSRF protection. The version identifier is also consistent with the release changes.

Full details: Docstring Coverage

Explanation

Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 4 files. (2 skipped: 2 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@VickyXAI
VickyXAI merged commit 998a4b0 into main Oct 22, 2026
5 checks passed
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.

1 participant