行业资讯
📅 2026/9/7 16:01:30
Crawl4AI v0.8.0 升级指南:Docker API Hooks 默认禁用、file:// URL 封锁与安全配置详解
Crawl4AI v0.8.0 升级指南Docker API Hooks 默认禁用、file:// URL 封锁与安全配置详解【免费下载链接】crawl4ai Crawl4AI: Open-source LLM Friendly Web Crawler Scraper. Dont be shy, join here: https://discord.gg/jP8KfhDhyN项目地址: https://gitcode.com/GitHub_Trending/craw/crawl4ai本篇基于仓库中的迁移文档 v0.8.0-upgrade-guide.md 编写面向从 v0.7.x 升级到 v0.8.0 的开发者重点覆盖两类破坏性变更——Docker API 的 Hooks 默认禁用与file://URL 封锁——的完整迁移路径并深入 server.py、config.yml、auth.py 等源码帮助你理解每项变更背后的安全动机、验证行为并在生产环境中正确完成升级。变更速览v0.8.0 的破坏性变更集中作用于 Docker API 部署形态官方迁移文档给出的速览表如下变更影响范围需要的操作Hooks 默认禁用使用 Docker API 且依赖 hooks 的用户设置CRAWL4AI_HOOKS_ENABLEDtruefile://URL 被封锁通过 API 读取本地文件的用户改用 Python 库直接处理安全修复所有 Docker API 用户立即升级这两项变更分别对应两个高危漏洞的修复Hooks 参数导致的远程代码执行RCE与file://URL 导致的本地文件包含LFI。完整的漏洞说明见 RELEASE_NOTES_v0.8.0.md其中 RCE 被定级为 CRITICALCVSS 10.0LFI 被定级为 HIGHCVSS 8.6。Step 1更新包PyPI 安装pip install --upgrade crawl4aiDocker 安装docker pull unclecode/crawl4ai:latest # 或 docker pull unclecode/crawl4ai:0.8.0从源码安装git pull origin main pip install -e .升级后建议核对运行版本。Docker API 的/health端点会返回当前包版本源码见 server.py 中的{status: ok, timestamp: ..., version: __version__}版本值直接取自 crawl4ai 包的__version__以保证服务端与库版本同步。Step 2判断你是否受影响官方迁移文档给出了明确的判定标准你受影响的条件满足其一即可使用 Docker API 部署形态在/crawl请求中使用hooks参数通过 API 端点使用file://URL你不受影响的条件仅将 Crawl4AI 作为 Python 库使用API 调用中不使用 hooks不通过 API 使用file://URL需要强调的是作为 Python 库直接使用时file://与raw:URL 依然完全可用。封锁行为只发生在 Docker API 的信任边界上。这一点可以从 async_crawler_strategy.py 得到印证库层面的arun仍显式支持file://、raw://、raw:前缀并在内部通过set_content()而非网络请求来加载内容。Step 3迁移 Hooks 用法v0.8.0 之前的行为Hooks 默认生效无需任何配置即可在请求中注入 hook 函数# 这在 v0.7.x 中无需任何配置即可工作 curl -X POST http://localhost:11235/crawl \ -H Content-Type: application/json \ -d { urls: [https://example.com], hooks: { code: { on_page_context_created: async def hook(page, context, **kwargs):\n await context.add_cookies([...])\n return page } } }问题在于hook 代码的受限沙箱中曾经保留了__import__内建函数攻击者可借此导入os、subprocess等模块执行任意命令——这就是被修复的 RCE 漏洞。v0.8.0 的修复策略是双管齐下从允许的内建函数列表中移除__import__同时让 Hooks 默认关闭。v0.8.0 之后的行为从源码看Docker API 在启动时读取环境变量决定 Hooks 开关默认值为falseserver.py# Hooks are disabled by default for security (RCE risk). Set to true to enable. HOOKS_ENABLED os.environ.get(CRAWL4AI_HOOKS_ENABLED, false).lower() true因此如果你确实需要 Hooks必须显式开启。当未开启而请求携带hooks参数时/crawl与/crawl/stream两个端点都会立即返回 403server.py、server.pyif crawl_request.hooks and not HOOKS_ENABLED: raise HTTPException(403, Hooks are disabled. Set CRAWL4AI_HOOKS_ENABLEDtrue to enable.)开启方式方式 A环境变量推荐在docker run命令或docker-compose.yml中设置# In your Docker run command or docker-compose.yml export CRAWL4AI_HOOKS_ENABLEDtrue# docker-compose.yml services: crawl4ai: image: unclecode/crawl4ai:0.8.0 environment: - CRAWL4AI_HOOKS_ENABLEDtrue方式 BKubernetesenv: - name: CRAWL4AI_HOOKS_ENABLED value: true安全警告仅在满足以下全部条件时才应开启 Hooks你信任所有能访问该 API 的用户API 未暴露到公共互联网已经部署了其他认证/授权机制默认配置 config.yml 中也有同样警示Set CRAWL4AI_HOOKS_ENABLEDtrue only if you need hooks (RCE risk)。Step 4迁移 file:// URL 用法v0.8.0 之前的行为此前可以通过 API 端点直接读取服务器本地文件# 这在 v0.7.x 中可以通过 API 工作 curl -X POST http://localhost:11235/execute_js \ -d {url: file:///var/data/page.html, scripts: [document.title]}这正是 LFI 漏洞的攻击向量file:///etc/passwd一类的 URL 会被浏览器加载从而把服务器任意文件内容返回给调用方。v0.8.0 之后的 URL 校验机制从源码看v0.8.0 引入了统一的 URL scheme 校验函数server.pyALLOWED_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, fURL must start with {schemes}) validate_url_destination(url)要点有三默认白名单只有http://与https://file://、javascript:、data:、ftp://等 scheme 一律被 400 拒绝部分端点如/html、/markdown允许raw:/raw://前缀用于直接提交 HTML 内容而不经过网络请求scheme 校验之后还会调用validate_url_destination做 SSRF 目的地址校验两者共同构成端点级的 URL 信任边界。仓库中的安全测试覆盖了这一行为test_security_fixes.py 断言file:///etc/passwd、Windows 路径file:///C:/Windows/System32/config/sam、javascript:、data:均被拦截而raw:html/html仅在allow_rawTrue时放行端到端脚本 run_security_tests.py 则对/execute_js、/screenshot、/pdf、/html四个端点逐一发送file:///etc/passwd并断言返回 400。三种迁移方案方案 A直接使用 Python 库本地文件处理本就应该在库层面完成arun原生支持file://from crawl4ai import AsyncWebCrawler, CrawlerRunConfig async def process_local_file(): async with AsyncWebCrawler() as crawler: result await crawler.arun( urlfile:///var/data/page.html, configCrawlerRunConfig(js_code[document.title]) ) return result方案 B使用raw:协议提交 HTML 内容如果你手里已经有 HTML 文本可以直接通过 API 端点提交无需落到服务器磁盘上# 读取文件内容后以 raw: 前缀提交 HTML_CONTENT$(cat /var/data/page.html) curl -X POST http://localhost:11235/html \ -H Content-Type: application/json \ -d {\url\: \raw:$HTML_CONTENT\}实现上raw:前缀后的字符串就是待处理的 HTML在 async_crawler_strategy.py 中策略层会剥离raw://6 字符或raw:4 字符前缀取出纯 HTML 内容后用set_content()注入页面完全绕过网络抓取。方案 C创建预处理服务如果流水线必须走 API可以在 API 之前加一层受信任的预处理服务由它调用 Python 库处理本地文件# preprocessing_service.py from fastapi import FastAPI from crawl4ai import AsyncWebCrawler app FastAPI() app.post(/process-local) async def process_local(file_path: str): async with AsyncWebCrawler() as crawler: result await crawler.arun(urlffile://{file_path}) return result.model_dump()补充说明当前仓库中/execute_js端点本身也已默认关闭需设置CRAWL4AI_EXECUTE_JS_ENABLEDtrue才可用server.py因为其风险模型是任意 JS SSRF。如果你的流程依赖该端点升级后需同时配置这一开关。Step 5审查安全配置生产环境推荐设置迁移文档推荐的config.yml安全段如下# config.yml security: enabled: true jwt_enabled: true https_redirect: true # If behind HTTPS proxy trusted_hosts: - your-domain.com - api.your-domain.com对照仓库自带的默认配置 config.yml各字段含义可进一步细化enabled: true启用安全中间件栈jwt_enabled默认false生产建议置true启用 JWT 认证api_token默认空串。设置后/token端点必须出示该密钥才能签发 JWT同时它也是静态 API token 的来源也可用环境变量CRAWL4AI_API_TOKEN注入。若完全未设置服务端启动时会打印警告日志提示所有端点处于未认证状态server.pyhttps_redirect置于 HTTPS 反向代理之后时启用强制跳转trusted_hosts默认[*]生产环境应收紧为明确域名列表cors_allow_origins默认拒绝deny-by-default仅显式列出的来源可跨域访问headers默认已启用X-Content-Type-Options: nosniff、X-Frame-Options: DENY、CSP 与 HSTS 等安全响应头。除安全段外config.yml 还定义了limits请求体大小上限 10 MiB、深爬页面/深度预算、后台任务队列容量与rate_limiting默认1000/minute两类资源治理配置用于防 DoS升级后建议一并核对。环境变量# JWT 认证必需 export SECRET_KEYyour-secure-random-key-minimum-32-characters # 仅在需要 hooks 时设置 export CRAWL4AI_HOOKS_ENABLEDtrue关于SECRET_KEYauth.py 的解析逻辑值得注意已知弱值会直接触发 FATAL 退出并提示用secrets.token_hex(32)生成强密钥长度不足最小要求32 字符同样拒绝启动认证已启用但未设置SECRET_KEY时服务端会生成一个临时密钥并告警——它在每次重启后变化会导致此前签发的所有 token 失效。因此任何真实部署都必须显式固定该值。生成安全的 Secret Keyimport secrets print(secrets.token_urlsafe(32))Step 6验证你的集成迁移文档提供了一个快速验证脚本覆盖升级后必须确认的三条行为基线基础抓取可用、Hooks 默认被 403 拦截、file://被 400 拦截import asyncio import aiohttp async def test_upgrade(): base_url http://localhost:11235 # Test 1: Basic crawl should work async with aiohttp.ClientSession() as session: async with session.post( f{base_url}/crawl, json{urls: [https://example.com]} ) as resp: assert resp.status 200, Basic crawl failed print(✓ Basic crawl works) # Test 2: Hooks should be blocked (unless enabled) async with aiohttp.ClientSession() as session: async with session.post( f{base_url}/crawl, json{ urls: [https://example.com], hooks: {code: {on_page_context_created: async def hook(page, context, **kwargs): return page}} } ) as resp: if resp.status 403: print(✓ Hooks correctly blocked (default)) elif resp.status 200: print(! Hooks enabled - ensure this is intentional) # Test 3: file:// should be blocked async with aiohttp.ClientSession() as session: async with session.post( f{base_url}/execute_js, json{url: file:///etc/passwd, scripts: [1]} ) as resp: assert resp.status 400, file:// should be blocked print(✓ file:// URLs correctly blocked) asyncio.run(test_upgrade())如果你希望跑仓库自带的完整安全回归可以查看 deploy/docker/tests 目录除上文提到的 test_security_fixes.py 与 run_security_tests.py 外还有 test_security_ssrf_crawl.py断言validate_url_scheme必须级联调用目的地址校验、raw:URL 跳过网络校验等测试可作为验收清单使用。故障排查Hooks are disabled 错误症状API 返回 403detail 为 Hooks are disabled. Set CRAWL4AI_HOOKS_ENABLEDtrue to enable.对应 server.py 的抛出点。解决如果业务确实需要 hooks按 Step 3 设置CRAWL4AI_HOOKS_ENABLEDtrue并重启容器否则应移除请求中的hooks字段。URL must start with http://, https:// 错误症状使用file://URL 时 API 返回 400。当前代码中该错误信息随端点略有差异——/markdown端点提示 Must start with http://, https://, or for raw HTML (raw:, raw://)server.py而经validate_url_scheme的端点则列出其允许白名单。解决改用 Python 库直接处理本地文件或按 Step 4 方案 B 使用raw:协议提交 HTML 内容。启用 JWT 后出现 401 Unauthorized症状API 返回 401 Unauthorized。解决先获取 tokenPOST /token提交你的凭证该端点定义见 server.py在后续请求头携带 tokenAuthorization: Bearer token。token 由 auth.py 基于 HS256 算法签发decode_token对算法白名单做严格校验。若配置了security.api_token/token端点本身也需要出示该静态密钥才能换取 JWT。回滚方案如遇集成问题需要临时回滚# PyPI pip install crawl4ai0.7.6 # Docker docker pull unclecode/crawl4ai:0.7.6警告回滚会重新暴露 RCE 与 LFI 两个安全漏洞。官方文档明确建议回滚只能是临时手段且期间应将 API 限制在受信任网络内尽快修复集成问题后再次升级到 v0.8.0 或更高版本。参考资料完整变更清单RELEASE_NOTES_v0.8.0.md版本变更日志CHANGELOG.md安全漏洞披露流程SECURITY.mdDocker API 服务实现server.py默认部署配置config.ymlJWT 认证实现auth.py安全回归测试test_security_fixes.py、run_security_tests.py【免费下载链接】crawl4ai Crawl4AI: Open-source LLM Friendly Web Crawler Scraper. Dont be shy, join here: https://discord.gg/jP8KfhDhyN项目地址: https://gitcode.com/GitHub_Trending/craw/crawl4ai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考