首页
/ Crawl4AI Docker API 安全通告解读:RCE 与 LFI 漏洞根因、修复验证与防护加固

Crawl4AI Docker API 安全通告解读:RCE 与 LFI 漏洞根因、修复验证与防护加固

2026-09-06 18:09:42作者:蔡丛锟

本篇文章以 Crawl4AI 仓库中官方安全通告草稿 docs/security/GHSA-DRAFT-RCE-LFI.md 为核心骨架,深度剖析 Crawl4AI Docker API 部署模式中于 v0.8.0 修复的两个高危漏洞:/crawl 端点 hooks 参数导致的远程代码执行(RCE,CVSS 10.0),以及 /execute_js/screenshot/pdf/html 端点接受 file:// URL 导致的本地文件包含(LFI,CVSS 8.6)。文章将逐一还原攻击载荷与影响面,并对照当前仓库中的加固实现(deploy/docker/server.pyhook_registry.pyegress_broker.py 及安全回归测试)验证修复是否落地,最后给出面向自托管部署的防护清单。读者读完可完整掌握这两条漏洞的来龙去脉、如何验证修复,以及升级与加固的实操方法。


通告背景与适用范围

该安全通告草稿记录了 Crawl4AI Docker API 部署形态(即 deploy/docker/ 目录下的 FastAPI 服务)在 v0.8.0 之前存在的两条漏洞。两条漏洞均由安全研究机构 ProjectDiscovery 的 Neo 发现并上报。通告中给出了标准的披露要素:

要素 漏洞一:Hooks 参数 RCE 漏洞二:file:// URL LFI
严重等级 Critical(严重) High(高危)
CVSS 3.1 10.0(AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H) 8.6(AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N)
CWE CWE-94(代码生成控制不当) CWE-22(受限目录路径名限制不当)
受影响版本 < 0.8.0 < 0.8.0
修复版本 0.8.0 0.8.0
攻击前提 无需认证 无需认证

说明:通告草稿原文中 References 指向外部 GitHub 页面。在本文中,请以仓库内文档为准:v0.8.0 发布说明v0.8.0 升级指南。仓库当前版本已迭代至 v0.9.0(见 crawl4ai/version.py),修复代码均已在当前代码库中生效。

从攻击视角看,两条漏洞的共同点是:Docker API 面向网络公开、默认无认证,而服务端把「用户提供的输入」当成了「可信代码/可信 URL」来执行。这是所有将爬虫能力封装成 HTTP 服务时都必须正视的信任边界问题。


漏洞一:通过 Hooks 参数实现远程代码执行(RCE)

漏洞成因与攻击向量

Crawl4AI SDK 的 AsyncWebCrawler 支持通过 crawler_strategy.set_hook(...) 在页面生命周期关键节点(如 on_page_context_createdbefore_goto 等)挂载 Python 回调,用于注入认证 Cookie、拦截资源、滚动页面等场景(仓库示例见 docs/examples/hooks_example.py)。

漏洞版本中,Docker API 的 /crawl 端点接收一个 hooks 参数,并直接对其中携带的 Python 源代码调用 exec() 执行;更致命的是,该受限执行环境(allowed_builtins)中保留了 __import__ 内建函数——攻击者因此可以突破“受限命名空间”,导入任意模块并执行系统命令。

通告给出的最小攻击载荷如下:

POST /crawl
{
  "urls": ["https://example.com"],
  "hooks": {
    "code": {
      "on_page_context_created": "async def hook(page, context, **kwargs):\n    __import__('os').system('malicious_command')\n    return page"
    }
  }
}

请求体中没有任何需要认证的字段:__import__('os') 拿到 os 模块后直接调用 .system(...),即可在服务端进程内执行任意 shell 命令。

影响面

通告明确指出,未认证攻击者利用该漏洞可以:

  • 执行任意系统命令;
  • 读写服务器上的任意文件;
  • 窃取敏感数据(环境变量、API Key 等);
  • 以服务进程身份向内网横向移动;
  • 完全控制服务器。

由于 Docker API 容器常被授予一定特权、且进程内往往持有 Redis、LLM Provider 凭据等敏感信息,RCE 的实际破坏力等同于服务器沦陷。

当前代码中的修复验证

通告记载的修复分三步:① 从 allowed_builtins 中移除 __import__;② 默认关闭 hooks(CRAWL4AI_HOOKS_ENABLED=false);③ 用户需显式开启才能使用 hooks。对照当前仓库源码,可以确认修复不仅落地,而且进一步深化:

1. Hooks 默认关闭,未开启时直接拒绝。deploy/docker/server.py 顶部:

HOOKS_ENABLED = os.environ.get("CRAWL4AI_HOOKS_ENABLED", "false").lower() == "true"

/crawl/crawl/stream 两个入口在接收含 hooks 的请求时会先做开关检查,未开启直接返回 403:

if crawl_request.hooks and not HOOKS_ENABLED:
    raise HTTPException(403, "Hooks are disabled. Set CRAWL4AI_HOOKS_ENABLED=true to enable.")

相关逻辑位于 deploy/docker/server.pycrawl/crawl_stream 处理器中。

2. 不再接受任意 Python 代码,改为「声明式动作注册表」。 当前仓库中,通告提到的 hook_manager.py 已不再存在,取而代之的是 deploy/docker/hook_registry.py。其模块 docstring 明确写道:旧的 hook_manager.py 通过 exec() 执行用户 Python,其沙箱“unsound”(可通过 __subclasses__ 的 MRO 遍历、注入的模块 __globals__、栈帧检查等手段逃逸),在进程内不存在安全运行攻击者 Python 的可行方案

因此新设计改为:请求只能从固定的一组声明式 ACTION 中选择,参数用 Pydantic 模型做 schema 校验,每个 ACTION 由服务端编写、只调用某一个特定的 Playwright API,用户字符串永远不会到达解释器:

动作名 绑定 hook 点 允许参数(含边界)
block_resources on_page_context_created resource_types 仅允许 image/stylesheet/font/media
add_cookies on_page_context_created 至多 20 个 Cookie,字段长度受限
set_headers before_goto 至多 20 个 header,名称正则校验、拒绝换行控制字符
scroll_to_bottom before_retrieve_html max_steps ≤ 50,delay_ms ≤ 5000
wait_for_timeout before_retrieve_html timeout_ms ≤ 60000

build_declarative_hooks()deploy/docker/hook_registry.py)会拒绝未知动作(HookValidationError → HTTP 400),并限制单个请求最多 10 条 hook 规格。例如“拦截图片资源”这一原本需要用自定义 Python 实现的诉求,现在写成:

POST /crawl
{
  "urls": ["https://example.com"],
  "hooks": {
    "hooks": [
      { "action": "block_resources", "params": { "resource_types": ["image", "media"] } },
      { "action": "scroll_to_bottom", "params": { "max_steps": 5, "delay_ms": 300 } }
    ]
  }
}

动作与参数说明可通过 GET /hooks/info(见 deploy/docker/server.pyget_hooks_info)随时查询。真正需要任意 hook 代码的高级用户,通告与代码注释给出的建议是改用自托管进程内 SDK 构建(Python 侧 crawler_strategy.set_hook(...) 仍保留给受信任代码使用),而不是把不受信代码暴露给 Docker API。

配置侧与文档侧的一致性

  • 默认安全配置在 deploy/docker/config.yml 的安全区注释中明确提示:Set CRAWL4AI_HOOKS_ENABLED=true only if you need hooks (RCE risk)
  • 升级指南 docs/migration/v0.8.0-upgrade-guide.md 提供了 docker-compose/环境变量开启 hooks 的完整迁移步骤;
  • 安全运维基线见仓库根目录 SECURITY.md:hooks 默认关闭,仅在确有必要时显式开启。

特别提醒:若你确实需要 hooks 功能,请务必评估“调用该 API 的请求方是否全部可信”。因为一旦 CRAWL4AI_HOOKS_ENABLED=true,任何能打到该端点的请求都获得了声明式 hook 的执行能力,此时必须叠加认证(见下文加固清单)。


漏洞二:通过 file:// URL 实现本地文件包含(LFI)

漏洞成因与攻击向量

Crawl4AI SDK 本身支持以 file:// 读取本地 HTML 文件(升级指南也明确建议本地文件处理走 Python 库)。但漏洞版本的 Docker API 中,/execute_js/screenshot/pdf/html 端点把用户提交的 URL 直接交给浏览器内核去访问,而没有做 URL scheme 白名单校验。这意味着攻击者可以让服务端浏览器代为读取宿主机文件系统上的任意文件。

通告给出的最小攻击载荷:

POST /execute_js
{
  "url": "file:///etc/passwd",
  "scripts": ["document.body.innerText"]
}

通过 file:///etc/passwd 让浏览器加载本地文件,再借 /execute_js 的脚本取回 document.body.innerText,一份系统账户文件就通过 API 响应被带了出来。

影响面

  • 读取 /etc/passwd/etc/shadow、应用配置文件等敏感文件;
  • 通过 /proc/self/environ 读取进程环境变量(常含各类密钥);
  • 摸清内部应用结构,为进一步攻击做信息收集;
  • 可能直接读取到凭据与 API Key。

由于爬虫容器往往与 Redis、LLM Provider 等共用编排网络,LFI 叠加环境变量泄露的破坏同样不容小觑。

当前代码中的修复验证

通告记载的修复为:增加 URL scheme 校验,阻止 file://javascript:data: 及其他非 HTTP scheme,仅允许 http://https://raw:

对照 deploy/docker/server.py 的实现,校验函数与白名单如下:

ALLOWED_URL_SCHEMES = ("http://", "https://")
ALLOWED_URL_SCHEMES_WITH_RAW = ("http://", "https://", "raw:", "raw://")

def validate_url_scheme(url: str, allow_raw: bool = False) -> None:
    """Validate URL scheme (LFI) and destination (SSRF)."""
    allowed = ALLOWED_URL_SCHEMES_WITH_RAW if allow_raw else ALLOWED_URL_SCHEMES
    if not url.startswith(allowed):
        schemes = ", ".join(allowed)
        raise HTTPException(400, f"URL must start with {schemes}")
    validate_url_destination(url)

其中:

  • /screenshot/pdf/execute_js 默认调用 validate_url_scheme(body.url)(不允许 raw);
  • /html 因业务需要支持内联 HTML,调用 validate_url_scheme(body.url, allow_raw=True),即额外放行 raw:/raw://(该 scheme 指向内联 HTML 内容,不触发任何网络或本地文件读取)。

screenshot/pdf/html/execute_js 端点均位于 deploy/docker/server.py@app.post(...) 路由中。file://javascript:data:ftp://、空 URL 与相对路径(/etc/passwd../../../etc/passwd)都会在校验第一步被 400 拒绝。

进一步加固:除 scheme 校验外,validate_url_scheme 内部还会继续调用 validate_url_destination(),把 SSRF 保护串进链路(见下文“纵深防御”)。同时,/execute_js 端点在当前版本中默认整体禁用,需设置 CRAWL4AI_EXECUTE_JS_ENABLED=true 才会开放(见 deploy/docker/server.pyexecute_js 处理器与 deploy/docker/tests/test_security_2026_04_b2.py 的断言),从端点级进一步收窄攻击面。

修复后的正确用法

通告与 v0.8.0 发布说明 给出的迁移建议高度一致:需要处理本地 HTML 的场景,请使用 Python 库而非 Docker API

from crawl4ai import AsyncWebCrawler

async with AsyncWebCrawler() as crawler:
    result = await crawler.arun(url="file:///path/to/file.html")

Docker API 侧只面向 http(s) 网页(或通过 raw: 直接传入 HTML 字符串),二者职责边界清晰。


安全回归测试:修复如何被机器验证

仓库在 deploy/docker/tests/ 目录下沉淀了大量针对这两条漏洞的安全回归用例,是验证“修复是否真的生效、未来是否回退”的第一手证据:

上述测试与 deploy/docker/SECURITY-VERIFY.md 可组合成一套完整的 Docker API 安全验收流程,建议自托管用户将其纳入 CI 或发布前的安全门禁。


纵深防御:与修复配套的周边加固

两条漏洞的修复并非孤立补丁,而是被纳入了 Docker API 的整体信任边界体系。结合源码可以梳理出与本次通告直接相关的几层纵深防御:

1. SSRF 防护(URL 目标校验)。 deploy/docker/utils.py 中的 validate_url_destination 负责拦截指向内网/私有网络的 URL,并在 deploy/docker/egress_broker.py 中做“解析并固定目标 IP(pin)+ 强制出网”的双保险:既拒绝非全局 IP(含 IPv4-mapped IPv6、NAT64 等变体绕过),又防止后台抓取被重绑定/重定向到内网。ALLOW_INTERNAL_URLS 默认关闭。

2. 不可信配置的溯源闸门。 /crawl 等端点对 browser_config/crawler_config 使用 Provenance.UNTRUSTED 加载(见 deploy/docker/api.pycrawl4ai/async_configs.py),凡请求体尝试设置危险能力字段都会抛 UntrustedConfigError 并被映射为 HTTP 400,从源头杜绝“配置文件投毒”。

3. 端点级能力裁剪。 hooks 需 CRAWL4AI_HOOKS_ENABLED=true/execute_jsCRAWL4AI_EXECUTE_JS_ENABLED=true,均默认关闭;配置文件内还包含任务墙钟超时、内存阈值、每调用者配额等运行时约束(见 deploy/docker/config.yml)。

4. 错误信息不泄露内部细节。 deploy/docker/server.py 的全局异常处理器对 5xx 一律返回通用错误 + correlation_id,完整细节仅记录在服务端日志,避免把内部路径、依赖版本、解析到的内网 IP 或密钥回显给客户端。

5. 认证层。 security.api_token/token 签发 JWT 的机制(deploy/docker/server.py get_token)可在配置文件中显式开启(jwt_enabled)。


加固与升级操作清单

结合通告的 Mitigation 与仓库现状,自托管 Docker API 的落地顺序建议如下:

  1. 立即升级到已修复版本(通告标注 0.8.0,仓库当前为 0.9.0),不要停留在 < 0.8.0 的旧镜像上;
  2. 保持 hooks 与 /execute_js 默认关闭:不要设置 CRAWL4AI_HOOKS_ENABLED=true / CRAWL4AI_EXECUTE_JS_ENABLED=true,除非所有 API 调用方完全可信;如确需开启 hooks,改用文章第一节展示的声明式 ACTION,而非任何形式的原始代码字段;
  3. 启用认证:在 deploy/docker/config.yml 中设置随机强 api_token 并开启 jwt_enabled;未配置 api_token/token 会“fail closed”拒绝发号;
  4. 网络层收敛:若短时间内无法升级,可先行关闭/阻断 /crawl/execute_js 等高风险端点,并加装认证与网络级过滤(通告给出的临时缓解措施);
  5. 本地 HTML 处理一律走 Python SDK,不要通过 API 传 file://
  6. 跑一遍安全回归:参照 deploy/docker/tests/test_security_fixes.pydeploy/docker/tests/run_security_tests.py,确认 scheme 校验、hooks 开关与默认拒绝姿态均符合预期。

关于通告本身的组织与发布

原文档末尾给出了将草稿发布为正式安全通告的操作流程(填表字段:Ecosystem=PyPI、包名=crawl4ai、Affected < 0.8.0、Patched 0.8.0、Severity 分别取 Critical/High)。其核心要点可归纳为:发布后系统会分配 GHSA ID、可选申请 CVE、并向开启安全告警的订阅用户推送通知,因此协调披露节奏与修复版本发版时间至关重要。这一点与仓库中 CHANGELOG.mddocs/blog/release-v0.8.0.md 记录的安全修复条目相互印证。


小结

Crawl4AI v0.8.0 修复的这两条漏洞,本质上是**“把不可信输入交给代码解释器”与“把不可信 URL 交给浏览器”**两个经典信任边界错误的 Docker API 版本。对照仓库源码可以确认:修复不仅如通告所述移除了 __import__、默认关闭 hooks、白名单化 URL scheme,更演进为「声明式 hook 注册表 + 参数 schema 校验 + scheme/SSRF 双重校验 + 端点级默认关闭 + 统一错误处理」的多层防御体系。对于所有自托管用户,最稳妥的策略是:升级到已修复版本、保持高风险能力默认关闭、始终开启认证,并让 deploy/docker/tests/ 下的安全回归测试成为发布流程的固定一环。相关升级细节还可继续参考 docs/migration/v0.8.0-upgrade-guide.mdv0.8.0 发布说明

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.74 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.81 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
595
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
920
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.63 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
518
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
389