Conversation
The SSRF cluster (7a6fe9b, 48f5c42, 7ef04ae) sealed browser_snapshot, browser_vision, and _browser_eval against eval-navigated private pages, but browser_get_images bypasses _browser_eval and calls _run_browser_command("eval", ...) directly. An eval-driven navigation to a private address followed by browser_get_images would leak image src URLs and alt text from the private page. Add the same _eval_ssrf_guard_active + _current_page_private_url recheck before returning image data, matching the pattern established by the sibling guards. 5 new tests cover: block on private page, allow on public page, skip for local backend, skip when private URLs allowed, no guard needed on failed eval.
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary\n\nVerdict: LGTM\n\nExtends the private-network SSRF guard to browser_get_images. Sibling of the snapshot/vision/eval guards. Clean test coverage with parametrized fixtures for public/private page scenarios.\n\n---\nReviewed by Hermes Agent
tonydwb
left a comment
There was a problem hiding this comment.
Security fix (96 additions). Extends the existing private-network SSRF guard to browser_get_images, which previously bypassed _browser_eval's URL check. Includes test coverage. Clean sibling of the snapshot/vision/eval guards.
Reviewed by Hermes Agent
|
looks mergeable I found no source-level blocker in the browser private-network guard change. The patch closes the Security evidence:
Signed: GPT-5.5-xhigh in Codex |
|
Thanks for tightening this browser-tool boundary. I verified the premise against current GitHub main and did not find a source-level blocker. Current main at 9a0010f still has the gap: tools/browser_tool.py:3489 calls _run_browser_command(effective_task_id, "eval", [js_code]) inside browser_get_images, then tools/browser_tool.py:3491-3507 parses and returns image metadata without the private-page URL recheck. The PR applies the same existing guard shape used by sibling paths: _eval_ssrf_guard_active is defined at tools/browser_tool.py:3158, _current_page_private_url at tools/browser_tool.py:3198, and _browser_eval already blocks post-eval private pages at tools/browser_tool.py:3277-3288. The diff adds that check to browser_get_images before returning image src/alt data, and tests/tools/test_browser_get_images_ssrf.py covers the private block, public success, opt-out, and failed-eval cases. Salvageability looks high: this is a narrow security fix in one browser tool path, with focused tests and no new core surface, config, or prompt-cache implications. Automated hermes-sweeper review. |
Summary
The SSRF cluster (7a6fe9b, 48f5c42, 7ef04ae — PR #54132) sealed
browser_snapshot,browser_vision, and_browser_evalagainst eval-navigated private pages, butbrowser_get_imageswas missed.browser_get_imagesbypasses_browser_evaland calls_run_browser_command(effective_task_id, "eval", [js_code])directly, so none of the eval SSRF guards apply. After an eval-driven navigation to a private address (e.g.location.href = 'http://127.0.0.1:8080/'), callingbrowser_get_imageswould leak imagesrcURLs andalttext from the private page.Changes
tools/browser_tool.py: Add the same_eval_ssrf_guard_active()+_current_page_private_url()recheck tobrowser_get_images()before returning image data, matching the pattern from the snapshot/vision/eval guards.Test plan
test_browser_get_images_ssrf.py): blocks on private page, allows on public page, skips for local backend, skips when private URLs allowed, no guard on failed eval