Skip to content

Fix SSRF guard rejecting private proxies - #2762

Open
shard-c6 wants to merge 1 commit into
Graphify-Labs:v8from
shard-c6:fix-issue-2761
Open

Fix SSRF guard rejecting private proxies#2762
shard-c6 wants to merge 1 commit into
Graphify-Labs:v8from
shard-c6:fix-issue-2761

Conversation

@shard-c6

Copy link
Copy Markdown

Fixes #2761

This PR modifies the SSRF guard connection classes (_SSRFGuardedHTTPConnection and _SSRFGuardedHTTPSConnection) to be proxy-aware. When a request is explicitly configured to use a proxy, the private IP address check is bypassed for the proxy endpoint itself, while validate_url independently preserves SSRF protections for the final destination URL.

Changes:

  • Added _ProxyAwareHTTPConnection and _ProxyAwareHTTPSConnection subclasses to safely connect to proxies without applying IP blocking on the proxy's resolved address.
  • Updated _SSRFGuardedHTTPHandler and _SSRFGuardedHTTPSHandler to detect if the request is using a proxy (req.has_proxy() or req._tunnel_host) and dispatch to the correct connection type.

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 1 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

This PR adds proxy handling to the SSRF-guarded HTTP/HTTPS connection machinery in graphify/security.py. It introduces two new connection subclasses (_ProxyAwareHTTPConnection and _ProxyAwareHTTPSConnection) that skip the SSRF IP validation on the connect step, and updates the HTTP/HTTPS handlers to route requests through these proxy-aware classes when a proxy or tunnel host is detected on the request. The surface area is limited to the connection/handler classes governing outbound request routing.

Worth a look

  • HTTPS proxy CONNECT tunnel target not SSRF-validatedgraphify/security.py:234 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review Execution auto-disposal is off for this run; enable it (with sandbox isolation) to have Graphify try to confirm or refute this automatically.
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 1130 functions depend on the 47 functions this change touches.

Health — grade A; 10 existing hotspot(s) in the area this change touches (pre-existing, not introduced here):

  • _rebuild_code() — 95 callers, 51 callees (high)
  • build_merge() — 41 callers, 14 callees (high)
  • _extract_generic() — 18 callers, 23 callees (high)
  • extract_bash() — 40 callers, 10 callees (high)
  • extract_xaml() — 19 callers, 17 callees (high)
  • ingest_scip_json() — 76 callers, 4 callees (high)
  • to_json() — 44 callers, 6 callees (high)
  • dispatch_command() — 2 callers, 117 callees (high)
  • …and 2 more

Verification — 1130 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 420 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify http\_open.

The verifier did not have enough to check http\_open, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: method — first parameter is `self`, which needs a constructed instance (not synthesizable)

Could not verify: Could not verify https\_open.

The verifier did not have enough to check https\_open, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: method — first parameter is `self`, which needs a constructed instance (not synthesizable)

@fgtb

fgtb commented Aug 15, 2026

Copy link
Copy Markdown

user@rhovanion graphify % git checkout fix-issue-2761
Already on 'fix-issue-2761'
Your branch is up to date with 'origin/fix-issue-2761'.
Then user@rhovanion graphify % uv tool install --force .
...Installed 2 executables: graphify, graphify-mcp.

user@rhovanion graphify % cd ~/tmp ; graphify add https://www.bbc.co.uk
error: ingest: failed to fetch 'https://www.bbc.co.uk': <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for ''. (_ssl.c:1082)>
user@rhovanion graphify % graphify add https://wired.com
error: ingest: failed to fetch 'https://wired.com': <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for ''. (_ssl.c:1082)>

Looks like the proposed fix gets further than before, but it bumps into an SSL cert error. My proxy is running squid and functions fine for normal web browsing:

user@rhovanion Programming % curl -vI https://www.bbc.co.uk

  • Uses proxy env variable HTTPS_PROXY == 'http://:3128'
  • Host :3128 was resolved.
  • IPv6: (none)
  • IPv4: 192.168.64.1
  • Trying 192.168.64.1:3128...
  • Connected to (192.168.64.1) port 3128
  • CONNECT tunnel: HTTP/1.1 negotiated
  • allocate connect buffer
  • Establish HTTP proxy tunnel to www.bbc.co.uk:443

CONNECT www.bbc.co.uk:443 HTTP/1.1
Host: www.bbc.co.uk:443
User-Agent: curl/8.7.1
Proxy-Connection: Keep-Alive

< HTTP/1.1 200 Connection established
HTTP/1.1 200 Connection established
...

(private domain names removed for privacy).

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.

graphify add cannot use macOS system HTTP(S) proxy on a private/LAN address

2 participants