feat(tools): enable internet access by default (#4270)

* feat(tools): enable internet access by default

Enable web_fetch, web_search, http_request, and browser tools by
default so ZeroClaw has internet access out of the box. Security
remains fully toggleable via config (set enabled = false to disable).

- web_fetch: enabled with allowed_domains = ["*"]
- web_search: enabled with DuckDuckGo (free, no API key)
- http_request: enabled with allowed_domains = ["*"]
- browser: enabled with allowed_domains = ["*"], agent_browser backend
- text_browser: remains opt-in (requires external binary)

* fix(tests): update component test for browser enabled by default

Update config_nested_optional_sections_default_when_absent to expect
browser.enabled = true, matching the new default.
This commit is contained in:
Argenis 2026-03-22 19:07:12 -04:00 committed by Roman Tataurov
parent 17c3d467b0
commit 5a85225f40
No known key found for this signature in database
GPG Key ID: 70A51EF3185C334B
2 changed files with 19 additions and 17 deletions

View File

@ -2147,8 +2147,8 @@ fn default_browser_webdriver_url() -> String {
impl Default for BrowserConfig {
fn default() -> Self {
Self {
enabled: false,
allowed_domains: Vec::new(),
enabled: true,
allowed_domains: vec!["*".into()],
session_name: None,
backend: default_browser_backend(),
native_headless: default_true(),
@ -2163,7 +2163,9 @@ impl Default for BrowserConfig {
/// HTTP request tool configuration (`[http_request]` section).
///
/// Deny-by-default: if `allowed_domains` is empty, all HTTP requests are rejected.
/// Domain filtering: `allowed_domains` controls which hosts are reachable (use `["*"]`
/// for all public hosts, which is the default). If `allowed_domains` is empty, all
/// requests are rejected.
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct HttpRequestConfig {
/// Enable `http_request` tool for API interactions
@ -2187,8 +2189,8 @@ pub struct HttpRequestConfig {
impl Default for HttpRequestConfig {
fn default() -> Self {
Self {
enabled: false,
allowed_domains: vec![],
enabled: true,
allowed_domains: vec!["*".into()],
max_response_size: default_http_max_response_size(),
timeout_secs: default_http_timeout_secs(),
allow_private_hosts: false,
@ -2246,7 +2248,7 @@ fn default_web_fetch_allowed_domains() -> Vec<String> {
impl Default for WebFetchConfig {
fn default() -> Self {
Self {
enabled: false,
enabled: true,
allowed_domains: vec!["*".into()],
blocked_domains: vec![],
max_response_size: default_web_fetch_max_response_size(),
@ -2328,7 +2330,7 @@ fn default_web_search_timeout_secs() -> u64 {
impl Default for WebSearchConfig {
fn default() -> Self {
Self {
enabled: false,
enabled: true,
provider: default_web_search_provider(),
brave_api_key: None,
searxng_instance_url: None,
@ -9728,8 +9730,8 @@ mod tests {
let cfg = HttpRequestConfig::default();
assert_eq!(cfg.timeout_secs, 30);
assert_eq!(cfg.max_response_size, 1_000_000);
assert!(!cfg.enabled);
assert!(cfg.allowed_domains.is_empty());
assert!(cfg.enabled);
assert_eq!(cfg.allowed_domains, vec!["*".to_string()]);
}
#[test]
@ -11633,15 +11635,15 @@ default_temperature = 0.7
assert!(!c.composio.enabled);
assert!(c.composio.api_key.is_none());
assert!(c.secrets.encrypt);
assert!(!c.browser.enabled);
assert!(c.browser.allowed_domains.is_empty());
assert!(c.browser.enabled);
assert_eq!(c.browser.allowed_domains, vec!["*".to_string()]);
}
#[test]
async fn browser_config_default_disabled() {
async fn browser_config_default_enabled() {
let b = BrowserConfig::default();
assert!(!b.enabled);
assert!(b.allowed_domains.is_empty());
assert!(b.enabled);
assert_eq!(b.allowed_domains, vec!["*".to_string()]);
assert_eq!(b.backend, "agent_browser");
assert!(b.native_headless);
assert_eq!(b.native_webdriver_url, "http://127.0.0.1:9515");
@ -11706,8 +11708,8 @@ config_path = "/tmp/config.toml"
default_temperature = 0.7
"#;
let parsed = parse_test_config(minimal);
assert!(!parsed.browser.enabled);
assert!(parsed.browser.allowed_domains.is_empty());
assert!(parsed.browser.enabled);
assert_eq!(parsed.browser.allowed_domains, vec!["*".to_string()]);
}
// ── Environment variable overrides (Docker support) ─────────

View File

@ -401,7 +401,7 @@ fn config_nested_optional_sections_default_when_absent() {
assert!(parsed.channels_config.telegram.is_none());
assert!(!parsed.composio.enabled);
assert!(parsed.composio.api_key.is_none());
assert!(!parsed.browser.enabled);
assert!(parsed.browser.enabled);
}
#[test]