fix(browser): migrate snapshot/vision private-URL checks onto shared helper - #56583
fix(browser): migrate snapshot/vision private-URL checks onto shared helper#56583naterchrdsn wants to merge 1 commit into
Conversation
Related: fixes #56579 (snapshot/vision private-URL floor parity), part of the browser SSRF cluster #54132 / #56173. This is a defense-in-depth consistency fix — |
c884318 to
4919807
Compare
teknium1
left a comment
There was a problem hiding this comment.
Thanks for preserving the cloud-metadata floor across the snapshot and vision paths. The live bypass described in the body is not reproducible on current main: is_safe_url() already rejects metadata hostnames and always-blocked IPs regardless of the private-URL toggle (tools/url_safety.py:405-441). This is therefore a useful defense-in-depth consistency change.
Problems
- The patch does not use the shared helper it identifies. The changed guards at
tools/browser_tool.py:2973andtools/browser_tool.py:3941still duplicate the URL probe and predicate already centralized in_current_page_private_url()attools/browser_tool.py:3387-3412. Future changes to that helper can still drift from these two paths.
Suggested changes
- Route both guards through
_eval_ssrf_guard_active(effective_task_id)and_current_page_private_url(effective_task_id), preserving their current error payloads. The proposed regression tests can remain to verify the helper's always-blocked branch.
Automated hermes-sweeper review.
| @@ -2970,7 +2970,9 @@ def browser_snapshot( | |||
| _url_result.get("data", {}).get("result", "") | |||
| .strip().strip('"').strip("'") | |||
| ) | |||
| if _current_url and not _is_safe_url(_current_url): | |||
| if _current_url and ( | |||
There was a problem hiding this comment.
This still duplicates _current_page_private_url() rather than migrating to it. Please have both snapshot and vision call the shared helper after _eval_ssrf_guard_active(effective_task_id) so the probe, always-blocked floor, and future changes have one owner.
4919807 to
1da815d
Compare
|
Follow-up on the review: rebased onto current
Verification: |
1da815d to
8a9344e
Compare
Closes #56579
Problem
browser_snapshotandbrowser_visionused a weaker SSRF floor than the shared_current_page_private_urlhelper. Their inline checks only tested:This misses the
_is_always_blocked_url()predicate, which covers cloud-metadata addresses (169.254.169.254,169.254.169.253,100.100.100.200,metadata.google.internal). If_is_safe_urlwere to returnTruefor one of those addresses, the guard would silently pass and expose private page content via snapshot or vision.The shared
_current_page_private_urlhelper — already used correctly bybrowser_back,browser_console, andbrowser_get_images— applies both predicates:Fix
Add
_is_always_blocked_url(_current_url)to the condition in both inline guards so they match the shared helper:Two lines changed in
browser_tool.py.Tests
Added
TestSnapshotBlocksCloudMetadataViaAlwaysBlockedandTestVisionBlocksCloudMetadataViaAlwaysBlockedintests/tools/test_browser_snapshot_ssrf.py. Each test patches_is_safe_urlto returnTrue(simulating the gap) while_is_always_blocked_urlcorrectly identifies169.254.169.254— and asserts both functions still block the request.