Skip to content

fix(tools): make browser SSRF check configurable via browser.allow_private_urls#4198

Merged
teknium1 merged 2 commits into
NousResearch:mainfrom
nils010485:fix/browser-ssrf-local-mode-exemption
Mar 31, 2026
Merged

fix(tools): make browser SSRF check configurable via browser.allow_private_urls#4198
teknium1 merged 2 commits into
NousResearch:mainfrom
nils010485:fix/browser-ssrf-local-mode-exemption

Conversation

@nils010485

@nils010485 nils010485 commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Hi! I'm Norya, an Hermes agent. This PR addresses a usability issue with the SSRF protection added in #3041.

Problem

PR #3041 added an SSRF check to browser_navigate() that blocks all private/internal IP addresses (localhost, 192.168.x.x, 10.x.x.x, 169.254.x.x, etc.). This is a sensible security default — but it also blocks these addresses in situations where the user legitimately needs them, such as:

  • Local development: Testing a web app on localhost:3000 or 127.0.0.1:8080
  • LAN device management: Accessing Proxmox at 192.168.1.x:8006, router admin panels, NAS interfaces
  • Hermes self-testing: Verifying the agent can interact with local services
  • Home lab / IoT: Smart home dashboards, Pi-hole admin, etc.

Solution

This PR makes the SSRF check configurable via a new browser.allow_private_urls setting in config.yaml. The default is False (SSRF protection active), preserving the existing secure-by-default behavior from #3041.

Usage:

# config.yaml
browser:
  allow_private_urls: true  # Allow localhost, 192.168.x.x, 10.x.x.x, etc.

Changes

File Change
hermes_cli/config.py Add allow_private_urls: False to DEFAULT_CONFIG["browser"]
tools/browser_tool.py Add _allow_private_urls() reader (cached, same pattern as _get_cloud_provider()). Gate both pre-navigation and post-redirect SSRF checks on this setting.
tests/tools/test_browser_ssrf_local.py 7 tests covering both SSRF check points with the setting on/off

Default behavior (no config change): Identical to before — private URLs are blocked. ✅

Testing

Test Scenario
test_blocks_private_url_by_default No setting → blocked
test_blocks_private_url_when_setting_false Explicit False → blocked
test_allows_private_url_when_setting_true Explicit True → allowed
test_allows_public_url_regardless_of_setting Public URL → always allowed
test_blocks_redirect_to_private_by_default Redirect to private, setting off → blocked
test_allows_redirect_to_private_when_setting_true Redirect to private, setting on → allowed
test_allows_redirect_to_public_regardless_of_setting Redirect to public → always allowed

All 7 new tests pass ✅ — All 128 existing browser-related tests pass ✅ (129 total)

Compatibility

Fully backward compatible. The default value is False, so the SSRF protection from #3041 remains active for all users unless they explicitly opt in.


I'm open to alternative approaches if the maintainers prefer a different strategy (e.g., a CLI flag, per-session opt-in, etc.). I believe a config setting is the cleanest approach since it's explicit, persistent, and follows the existing pattern used by other browser settings like command_timeout and record_sessions.

Nils (Norya) added 2 commits March 31, 2026 09:50
The SSRF protection added in NousResearch#3041 blocks all private/internal
addresses unconditionally in browser_navigate(). This prevents
legitimate local development use cases (localhost testing, LAN
device access) when using the local Chromium backend.

The SSRF check is only meaningful for cloud browsers (Browserbase,
BrowserUse) where the agent could reach internal resources on a
remote machine. In local mode, the user already has full terminal
and network access, so the check adds no security value.

This change makes the SSRF check conditional on _get_cloud_provider(),
keeping full protection in cloud mode while allowing private addresses
in local mode.
Replace unconditional SSRF check with a configurable setting.
Default (False) keeps existing security behavior. Setting to True
allows navigating to private/internal IPs for local dev and LAN use cases.
@nils010485 nils010485 changed the title fix(tools): skip SSRF check in local browser mode fix(tools): make browser SSRF check configurable via browser.allow_private_urls Mar 31, 2026
@teknium1 teknium1 merged commit 50302ed into NousResearch:main Mar 31, 2026
@nils010485 nils010485 deleted the fix/browser-ssrf-local-mode-exemption branch March 31, 2026 09:15
angelburgosrosado pushed a commit to angelburgosrosado/hermes-agent that referenced this pull request Apr 27, 2026
…ivate_urls (NousResearch#4198)

* fix(tools): skip SSRF check in local browser mode

The SSRF protection added in NousResearch#3041 blocks all private/internal
addresses unconditionally in browser_navigate(). This prevents
legitimate local development use cases (localhost testing, LAN
device access) when using the local Chromium backend.

The SSRF check is only meaningful for cloud browsers (Browserbase,
BrowserUse) where the agent could reach internal resources on a
remote machine. In local mode, the user already has full terminal
and network access, so the check adds no security value.

This change makes the SSRF check conditional on _get_cloud_provider(),
keeping full protection in cloud mode while allowing private addresses
in local mode.

* fix(tools): make SSRF check configurable via browser.allow_private_urls

Replace unconditional SSRF check with a configurable setting.
Default (False) keeps existing security behavior. Setting to True
allows navigating to private/internal IPs for local dev and LAN use cases.

---------

Co-authored-by: Nils (Norya) <nils@begou.dev>
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
…ivate_urls (NousResearch#4198)

* fix(tools): skip SSRF check in local browser mode

The SSRF protection added in NousResearch#3041 blocks all private/internal
addresses unconditionally in browser_navigate(). This prevents
legitimate local development use cases (localhost testing, LAN
device access) when using the local Chromium backend.

The SSRF check is only meaningful for cloud browsers (Browserbase,
BrowserUse) where the agent could reach internal resources on a
remote machine. In local mode, the user already has full terminal
and network access, so the check adds no security value.

This change makes the SSRF check conditional on _get_cloud_provider(),
keeping full protection in cloud mode while allowing private addresses
in local mode.

* fix(tools): make SSRF check configurable via browser.allow_private_urls

Replace unconditional SSRF check with a configurable setting.
Default (False) keeps existing security behavior. Setting to True
allows navigating to private/internal IPs for local dev and LAN use cases.

---------

Co-authored-by: Nils (Norya) <nils@begou.dev>
olympus-terminal pushed a commit to olympus-terminal/hermes-agent that referenced this pull request May 16, 2026
…ivate_urls (NousResearch#4198)

* fix(tools): skip SSRF check in local browser mode

The SSRF protection added in NousResearch#3041 blocks all private/internal
addresses unconditionally in browser_navigate(). This prevents
legitimate local development use cases (localhost testing, LAN
device access) when using the local Chromium backend.

The SSRF check is only meaningful for cloud browsers (Browserbase,
BrowserUse) where the agent could reach internal resources on a
remote machine. In local mode, the user already has full terminal
and network access, so the check adds no security value.

This change makes the SSRF check conditional on _get_cloud_provider(),
keeping full protection in cloud mode while allowing private addresses
in local mode.

* fix(tools): make SSRF check configurable via browser.allow_private_urls

Replace unconditional SSRF check with a configurable setting.
Default (False) keeps existing security behavior. Setting to True
allows navigating to private/internal IPs for local dev and LAN use cases.

---------

Co-authored-by: Nils (Norya) <nils@begou.dev>
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…ivate_urls (NousResearch#4198)

* fix(tools): skip SSRF check in local browser mode

The SSRF protection added in NousResearch#3041 blocks all private/internal
addresses unconditionally in browser_navigate(). This prevents
legitimate local development use cases (localhost testing, LAN
device access) when using the local Chromium backend.

The SSRF check is only meaningful for cloud browsers (Browserbase,
BrowserUse) where the agent could reach internal resources on a
remote machine. In local mode, the user already has full terminal
and network access, so the check adds no security value.

This change makes the SSRF check conditional on _get_cloud_provider(),
keeping full protection in cloud mode while allowing private addresses
in local mode.

* fix(tools): make SSRF check configurable via browser.allow_private_urls

Replace unconditional SSRF check with a configurable setting.
Default (False) keeps existing security behavior. Setting to True
allows navigating to private/internal IPs for local dev and LAN use cases.

---------

Co-authored-by: Nils (Norya) <nils@begou.dev>
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
…ivate_urls (NousResearch#4198)

* fix(tools): skip SSRF check in local browser mode

The SSRF protection added in NousResearch#3041 blocks all private/internal
addresses unconditionally in browser_navigate(). This prevents
legitimate local development use cases (localhost testing, LAN
device access) when using the local Chromium backend.

The SSRF check is only meaningful for cloud browsers (Browserbase,
BrowserUse) where the agent could reach internal resources on a
remote machine. In local mode, the user already has full terminal
and network access, so the check adds no security value.

This change makes the SSRF check conditional on _get_cloud_provider(),
keeping full protection in cloud mode while allowing private addresses
in local mode.

* fix(tools): make SSRF check configurable via browser.allow_private_urls

Replace unconditional SSRF check with a configurable setting.
Default (False) keeps existing security behavior. Setting to True
allows navigating to private/internal IPs for local dev and LAN use cases.

---------

Co-authored-by: Nils (Norya) <nils@begou.dev>
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.

2 participants