Skip to content

Commit 6d4ed74

Browse files
fix(tools): pin SSRF checks to each redirect hop and peer IP
validate_url only inspected the original URL string, so scraping fetches could follow a 302 to an internal address or rebind DNS between check and connect. Route safe_get through an HTTPAdapter that re-validates every hop and connects to the authorised sockaddr, and let FORCE_SAFE_PATHS ignore a tenant-supplied escape hatch on managed workers. Co-authored-by: Rip&Tear <theCyberTech@users.noreply.github.com>
1 parent 27083f4 commit 6d4ed74

19 files changed

Lines changed: 561 additions & 51 deletions

docs/edge/ar/tools/web-scraping/scrapeelementfromwebsitetool.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mode: "wide"
99

1010
## الوصف
1111

12-
أداة `ScrapeElementFromWebsiteTool` مصممة لاستخراج عناصر محددة من المواقع باستخدام محددات CSS. تسمح هذه الأداة لوكلاء CrewAI باستخراج محتوى مستهدف من صفحات الويب، مما يجعلها مفيدة لمهام استخراج البيانات حيث تكون أجزاء محددة فقط من صفحة الويب مطلوبة.
12+
أداة `ScrapeElementFromWebsiteTool` مصممة لاستخراج عناصر محددة من المواقع باستخدام محددات CSS. تسمح هذه الأداة لوكلاء CrewAI باستخراج محتوى مستهدف من صفحات الويب، مما يجعلها مفيدة لمهام استخراج البيانات حيث تكون أجزاء محددة فقط من صفحة الويب مطلوبة. تمر الطلبات عبر مساعد HTTP الآمن ضد SSRF في CrewAI: يتم فحص عنوان URL المطلوب وكل قفزة إعادة توجيه مقابل النطاقات الخاصة والمحجوزة (بما في ذلك بيانات تعريف السحابة)، ويُثبَّت اتصال TCP على عنوان IP الذي اجتاز هذا الفحص.
1313

1414
## التثبيت
1515

docs/edge/ar/tools/web-scraping/scrapewebsitetool.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ mode: "wide"
1616
أداة مصممة لاستخراج وقراءة محتوى موقع محدد. قادرة على التعامل مع أنواع مختلفة من صفحات الويب عن طريق إجراء طلبات HTTP وتحليل محتوى HTML المستلم.
1717
يمكن أن تكون هذه الأداة مفيدة بشكل خاص لمهام استخراج البيانات من الويب وجمع البيانات أو استخراج معلومات محددة من المواقع.
1818

19+
تمر الطلبات عبر مساعد HTTP الآمن ضد SSRF في CrewAI: يتم فحص عنوان URL المطلوب وكل قفزة إعادة توجيه مقابل النطاقات الخاصة والمحجوزة (بما في ذلك بيانات تعريف السحابة)، ويُثبَّت اتصال TCP على عنوان IP الذي اجتاز هذا الفحص.
20+
1921
## التثبيت
2022

2123
ثبّت حزمة crewai_tools

docs/edge/en/tools/file-document/filereadtool.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,4 @@ To let an agent read a directory tree outside the working directory, point `base
7777
file_read_tool = FileReadTool(base_dir='/data')
7878
```
7979

80-
As a last resort, setting `CREWAI_TOOLS_ALLOW_UNSAFE_PATHS=true` disables path validation. This applies process-wide to every crewai-tools tool, including the SSRF protections on URL-fetching tools, so prefer `base_dir`.
80+
As a last resort, setting `CREWAI_TOOLS_ALLOW_UNSAFE_PATHS=true` disables path validation. This applies process-wide to every crewai-tools tool, including the SSRF protections on URL-fetching tools, so prefer `base_dir`. Managed workers should set `CREWAI_TOOLS_FORCE_SAFE_PATHS=true` so a tenant cannot disable those checks by exporting the escape hatch.

docs/edge/en/tools/web-scraping/scrapeelementfromwebsitetool.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mode: "wide"
99

1010
## Description
1111

12-
The `ScrapeElementFromWebsiteTool` is designed to extract specific elements from websites using CSS selectors. This tool allows CrewAI agents to scrape targeted content from web pages, making it useful for data extraction tasks where only specific parts of a webpage are needed.
12+
The `ScrapeElementFromWebsiteTool` is designed to extract specific elements from websites using CSS selectors. This tool allows CrewAI agents to scrape targeted content from web pages, making it useful for data extraction tasks where only specific parts of a webpage are needed. Fetches go through CrewAI's SSRF-safe HTTP helper: the requested URL and every redirect hop are checked against private and reserved ranges (including cloud metadata), and the TCP connection is pinned to an IP that passed that check.
1313

1414
## Installation
1515

docs/edge/en/tools/web-scraping/scrapewebsitetool.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ mode: "wide"
1616
A tool designed to extract and read the content of a specified website. It is capable of handling various types of web pages by making HTTP requests and parsing the received HTML content.
1717
This tool can be particularly useful for web scraping tasks, data collection, or extracting specific information from websites.
1818

19+
Fetches go through CrewAI's SSRF-safe HTTP helper: the requested URL and every redirect hop are checked against private and reserved ranges (including cloud metadata), and the TCP connection is pinned to an IP that passed that check.
20+
1921
## Installation
2022

2123
Install the crewai_tools package

docs/edge/ko/tools/web-scraping/scrapeelementfromwebsitetool.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mode: "wide"
99

1010
## 설명
1111

12-
`ScrapeElementFromWebsiteTool`은 CSS 선택자를 사용하여 웹사이트에서 특정 요소를 추출하도록 설계되었습니다. 이 도구는 CrewAI 에이전트가 웹 페이지에서 타겟이 되는 콘텐츠를 스크래핑할 수 있게 하여, 웹페이지의 특정 부분만이 필요한 데이터 추출 작업에 유용합니다.
12+
`ScrapeElementFromWebsiteTool`은 CSS 선택자를 사용하여 웹사이트에서 특정 요소를 추출하도록 설계되었습니다. 이 도구는 CrewAI 에이전트가 웹 페이지에서 타겟이 되는 콘텐츠를 스크래핑할 수 있게 하여, 웹페이지의 특정 부분만이 필요한 데이터 추출 작업에 유용합니다. 가져오기는 CrewAI의 SSRF 안전 HTTP 헬퍼를 거칩니다. 요청된 URL과 모든 리다이렉트 홉이 사설 및 예약 대역(클라우드 메타데이터 포함)에 대해 검사되며, TCP 연결은 그 검사를 통과한 IP에 고정됩니다.
1313

1414
## 설치
1515

docs/edge/ko/tools/web-scraping/scrapewebsitetool.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ mode: "wide"
1616
지정된 웹사이트의 내용을 추출하고 읽을 수 있도록 설계된 도구입니다. 이 도구는 HTTP 요청을 보내고 수신된 HTML 콘텐츠를 파싱함으로써 다양한 유형의 웹 페이지를 처리할 수 있습니다.
1717
이 도구는 웹 스크래핑 작업, 데이터 수집 또는 웹사이트에서 특정 정보를 추출하는 데 특히 유용할 수 있습니다.
1818

19+
가져오기는 CrewAI의 SSRF 안전 HTTP 헬퍼를 거칩니다. 요청된 URL과 모든 리다이렉트 홉이 사설 및 예약 대역(클라우드 메타데이터 포함)에 대해 검사되며, TCP 연결은 그 검사를 통과한 IP에 고정됩니다.
20+
1921
## 설치
2022

2123
crewai_tools 패키지를 설치하세요

docs/edge/pt-BR/tools/web-scraping/scrapeelementfromwebsitetool.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mode: "wide"
99

1010
## Descrição
1111

12-
A `ScrapeElementFromWebsiteTool` foi projetada para extrair elementos específicos de websites utilizando seletores CSS. Esta ferramenta permite que agentes CrewAI capturem conteúdos direcionados de páginas web, tornando-se útil para tarefas de extração de dados em que apenas partes específicas de uma página são necessárias.
12+
A `ScrapeElementFromWebsiteTool` foi projetada para extrair elementos específicos de websites utilizando seletores CSS. Esta ferramenta permite que agentes CrewAI capturem conteúdos direcionados de páginas web, tornando-se útil para tarefas de extração de dados em que apenas partes específicas de uma página são necessárias. As buscas passam pelo helper HTTP seguro contra SSRF do CrewAI: a URL solicitada e cada hop de redirecionamento são verificados contra faixas privadas e reservadas (incluindo metadados de nuvem), e a conexão TCP é fixada no IP que passou nessa verificação.
1313

1414
## Instalação
1515

docs/edge/pt-BR/tools/web-scraping/scrapewebsitetool.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ mode: "wide"
1616
Uma ferramenta desenvolvida para extrair e ler o conteúdo de um site especificado. Ela é capaz de lidar com diversos tipos de páginas web fazendo requisições HTTP e analisando o conteúdo HTML recebido.
1717
Esta ferramenta pode ser especialmente útil para tarefas de raspagem de dados, coleta de dados ou extração de informações específicas de sites.
1818

19+
As buscas passam pelo helper HTTP seguro contra SSRF do CrewAI: a URL solicitada e cada hop de redirecionamento são verificados contra faixas privadas e reservadas (incluindo metadados de nuvem), e a conexão TCP é fixada no IP que passou nessa verificação.
20+
1921
## Instalação
2022

2123
Instale o pacote crewai_tools

lib/crewai-tools/src/crewai_tools/security/safe_path.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
user-controlled or LLM-controlled inputs at runtime.
66
77
Set CREWAI_TOOLS_ALLOW_UNSAFE_PATHS=true to bypass validation (not
8-
recommended for production).
8+
recommended for production). Managed workers should set
9+
CREWAI_TOOLS_FORCE_SAFE_PATHS=true so a tenant cannot disable these
10+
checks by exporting the escape hatch on their own deployment.
911
"""
1012

1113
from __future__ import annotations
@@ -20,6 +22,7 @@
2022
logger = logging.getLogger(__name__)
2123

2224
_UNSAFE_PATHS_ENV = "CREWAI_TOOLS_ALLOW_UNSAFE_PATHS"
25+
_FORCE_SAFE_PATHS_ENV = "CREWAI_TOOLS_FORCE_SAFE_PATHS"
2326
_BYPASS_HINT = f"Set {_UNSAFE_PATHS_ENV}=true to bypass this check."
2427

2528

@@ -69,9 +72,26 @@ def format_sandbox_error(error: Exception, remedy: str) -> str:
6972
return f"{text} {remedy}".strip()
7073

7174

75+
def _env_flag_enabled(name: str) -> bool:
76+
return os.environ.get(name, "").lower() in ("true", "1", "yes")
77+
78+
7279
def _is_escape_hatch_enabled() -> bool:
73-
"""Check if the unsafe paths escape hatch is enabled."""
74-
return os.environ.get(_UNSAFE_PATHS_ENV, "").lower() in ("true", "1", "yes")
80+
"""Check if the unsafe paths escape hatch is enabled.
81+
82+
``CREWAI_TOOLS_FORCE_SAFE_PATHS`` wins: managed workers set it so a
83+
tenant-supplied ``CREWAI_TOOLS_ALLOW_UNSAFE_PATHS`` cannot clear the
84+
SSRF / path allow-list.
85+
"""
86+
if _env_flag_enabled(_FORCE_SAFE_PATHS_ENV):
87+
if _env_flag_enabled(_UNSAFE_PATHS_ENV):
88+
logger.warning(
89+
"%s is set; ignoring %s",
90+
_FORCE_SAFE_PATHS_ENV,
91+
_UNSAFE_PATHS_ENV,
92+
)
93+
return False
94+
return _env_flag_enabled(_UNSAFE_PATHS_ENV)
7595

7696

7797
def validate_file_path(path: str, base_dir: str | None = None) -> str:
@@ -161,8 +181,8 @@ def validate_directory_path(path: str, base_dir: str | None = None) -> str:
161181
]
162182

163183

164-
def _is_private_or_reserved(ip_str: str) -> bool:
165-
"""Check if an IP address is private, reserved, or otherwise unsafe."""
184+
def is_blocked_ip(ip_str: str) -> bool:
185+
"""Return True if *ip_str* is private, reserved, or otherwise unsafe to fetch."""
166186
try:
167187
addr = ipaddress.ip_address(ip_str)
168188
# Unwrap IPv4-mapped IPv6 addresses (e.g., ::ffff:127.0.0.1) to IPv4
@@ -187,6 +207,13 @@ def validate_url(url: str) -> str:
187207
DNS and checks that the target IP is not private or reserved (prevents
188208
SSRF to internal services and cloud metadata endpoints).
189209
210+
This checks the URL string it is handed. Callers that then fetch must
211+
use :func:`crewai_tools.security.safe_requests.safe_get` (or a session
212+
from :func:`crewai_tools.security.safe_requests.create_safe_session`)
213+
so redirect hops are re-validated and the connection is pinned to an
214+
authorised IP. Calling ``requests.get`` after this function re-resolves
215+
DNS and follows redirects without these checks.
216+
190217
Args:
191218
url: The URL to validate.
192219
@@ -232,7 +259,7 @@ def validate_url(url: str) -> str:
232259

233260
for _family, _, _, _, sockaddr in addrinfos:
234261
ip_str = str(sockaddr[0])
235-
if _is_private_or_reserved(ip_str):
262+
if is_blocked_ip(ip_str):
236263
raise ValueError(
237264
f"URL '{url}' resolves to private/reserved IP {ip_str}. "
238265
f"Access to internal networks is not allowed. "

0 commit comments

Comments
 (0)