
ImportError: from crewai_tools.security.safe_path import validate_url
快速结论:这是一个 SSRF 绕过漏洞,并非 Python 的 ImportError。问题出在 crewai-tools 的 validate_url 函数只做一次验证,而 requests.get 默认跟随重定向但不会再验证目标地址。优先排查你的 crewai-tools 是否更新到包含 safe_get 修复的版本。
问题场景
用户在使用 CrewAI 框架的 scrape 工具(如 ScrapeWebsiteTool 或 ScrapeElementFromWebsiteTool)时,AI agent 的 LLM 可以通过间接提示注入控制 website_url 参数。攻击者可以利用 HTTP 重定向或 DNS 重新绑定绕过 URL 安全验证,访问内部服务或云元数据端点(如 169.254.169.254)。
报错原文
Step 1: validate_url PASSED, returned: http://100.100.65.36:8771/
Step 2: validate_url correctly blocks direct internal URL 'http://127.0.0.1:8772/' (private/reserved IP)
Step 3: Final URL after redirects: http://127.0.0.1:8772/latest/meta-data/
Status: 200
Body fetched from INTERNAL service: 'INTERNAL-METADATA-SECRET-TOKEN-credentials=AKIA_ROOT'
*** SSRF CONFIRMED: validate_url passed, redirect reached BLOCKED 127.0.0.1, internal secret exfiltrated ***
原因分析
问题根源在于 validate_url 函数(位于 crewai_tools/security/safe_path.py:136)使用 socket.getaddrinfo() 解析主机名并拦截私有/保留 IP,但仅验证一次后返回原始 URL 字符串。随后在 scrape_website_tool.py:78-84 中,requests.get() 默认跟随 HTTP 重定向(allow_redirects=True 是默认行为),但不对重定向目标重新调用 validate_url。攻击者可以让 website_url 指向一个公开的主机,该主机返回 302 Location: http://169.254.169.254/latest/meta-data/,从而完全绕过 SSRF 防护。同样的设计缺陷也使其容易受到 DNS 重新绑定攻击。
环境排查
- 确认 crewai-tools 的版本:检查是否已合并 PR #6331(2026-06-26 合并,修复了 SSRF 重定向绕过)。
- 检查
scrape_website_tool.py和scrape_element_from_website.py是否已改为使用crewai_tools.security.safe_requests.safe_get()函数。 - 确认代码中
allow_redirects设置:该 Issue 指出allow_redirects在lib/中无处出现,默认总是启用重定向。 - 检查其他工具如
brave_search_tool、jina_scrape_website_tool等是否也存在类似安全风险。
解决步骤
- 更新 crewai-tools 到包含修复的版本:确保拉取最新的 main 分支,其中
scrape_website_tool.py和scrape_element_from_website.py已通过safe_get()迁移修复。 - 验证修复代码逻辑:确认
safe_get()函数设置了allow_redirects=False,并手动遍历重定向链,在每个Location头部目标上调用validate_url()后再跟随(并设置max_redirects上限)。同时确认该函数会在跨源跳转时剥离Authorization/Cookie/API 密钥等敏感头部。 - 审查其他工具:对于报告提到的其他工具(如
jina_scrape_website_tool),虽然它们调用的是固定的第三方 API,但在设计上应确保用户提供的 URL 不会被直接传递给requests.get()作为目标地址。 - 添加回归测试:在 crewai-tools 的测试套件中添加重定向和 DNS 重新绑定测试用例,覆盖以下场景:
- 公开 URL 返回 302 到内部 IP(如 127.0.0.1)
- 公开 URL 返回 302 到云元数据端点(如 169.254.169.254)
- DNS 重新绑定攻击
验证方法
确认问题已修复的方法:尝试重现该漏洞场景——用一个公开主机返回 302 Location: http://127.0.0.1:8772/latest/meta-data/,然后使用 validate_url 后跟 requests.get。如果修复成功,safe_get() 内部的 while 循环会在重定向目标上调用 validate_url(),并抛出 ValueError 而不是跟随重定向。同时确认无内部内容被提取。



