From c1f832a61025626f46de6ab9f4ee0120fd33772e Mon Sep 17 00:00:00 2001 From: coffee Date: Fri, 10 Apr 2026 11:36:46 +0800 Subject: [PATCH] fix(tools): guard against ValueError on int() env var and header parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three locations perform `int()` conversion on environment variables or HTTP headers without error handling, causing unhandled `ValueError` crashes when the values are non-numeric: 1. `send_message_tool.py` — `EMAIL_SMTP_PORT` env var parsed outside the try/except block; a non-numeric value crashes `_send_email()` instead of returning a user-friendly error. 2. `process_registry.py` — `TERMINAL_TIMEOUT` env var parsed without protection; a non-numeric value crashes the `wait()` method. 3. `skills_hub.py` — HTTP `Retry-After` header can contain date strings per RFC 7231; `int()` conversion crashes on non-numeric values. All three now fall back to their default values on `ValueError`/`TypeError`. --- tools/process_registry.py | 5 ++++- tools/send_message_tool.py | 5 ++++- tools/skills_hub.py | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/process_registry.py b/tools/process_registry.py index 39d3704b1..9f57d3eae 100644 --- a/tools/process_registry.py +++ b/tools/process_registry.py @@ -585,7 +585,10 @@ class ProcessRegistry: from tools.ansi_strip import strip_ansi from tools.terminal_tool import _interrupt_event - default_timeout = int(os.getenv("TERMINAL_TIMEOUT", "180")) + try: + default_timeout = int(os.getenv("TERMINAL_TIMEOUT", "180")) + except (ValueError, TypeError): + default_timeout = 180 max_timeout = default_timeout requested_timeout = timeout timeout_note = None diff --git a/tools/send_message_tool.py b/tools/send_message_tool.py index c7c71c8c6..91f752b41 100644 --- a/tools/send_message_tool.py +++ b/tools/send_message_tool.py @@ -689,7 +689,10 @@ async def _send_email(extra, chat_id, message): address = extra.get("address") or os.getenv("EMAIL_ADDRESS", "") password = os.getenv("EMAIL_PASSWORD", "") smtp_host = extra.get("smtp_host") or os.getenv("EMAIL_SMTP_HOST", "") - smtp_port = int(os.getenv("EMAIL_SMTP_PORT", "587")) + try: + smtp_port = int(os.getenv("EMAIL_SMTP_PORT", "587")) + except (ValueError, TypeError): + smtp_port = 587 if not all([address, password, smtp_host]): return {"error": "Email not configured (EMAIL_ADDRESS, EMAIL_PASSWORD, EMAIL_SMTP_HOST required)"} diff --git a/tools/skills_hub.py b/tools/skills_hub.py index 0c218c5b6..c73527ff2 100644 --- a/tools/skills_hub.py +++ b/tools/skills_hub.py @@ -1788,7 +1788,10 @@ class ClawHubSource(SkillSource): follow_redirects=True, ) if resp.status_code == 429: - retry_after = int(resp.headers.get("retry-after", "5")) + try: + retry_after = int(resp.headers.get("retry-after", "5")) + except (ValueError, TypeError): + retry_after = 5 retry_after = min(retry_after, 15) # Cap wait time logger.debug( "ClawHub download rate-limited for %s, retrying in %ds (attempt %d/%d)",