Ladybird 安全策略解析:安全漏洞上报渠道、判定范围边界与模糊测试(Fuzzing)支撑
Ladybird 的 SECURITY.md 定义了该项目的安全问题上报与负责任披露政策:由于 Ladybird 是尚未正式发布的早期开发软件,漏洞可安全地公开讨论,默认推荐通过公开 Issue 上报,同时也支持通过 GitHub 私密安全通告(Security Advisory)流程私下报告。结合仓库中的 模糊测试基础设施、Issue 模板 与相关 CMake 构建配置,本文完整拆解这条安全政策的实际运作方式,读完你将掌握:Ladybird 的安全问题应走哪条上报路径、哪些 Web 安全问题当前不在判定范围内、第三方库漏洞的责任边界在哪里,以及如何使用仓库自带的 Fuzz 工具链在本地和 OSS-Fuzz 上复现/发现安全问题。
政策前提:Ladybird 当前的安全状态定位
SECURITY.md 开篇即明确了整个政策的基础假设:
Ladybird is unreleased software still in early development, and so bugs and vulnerabilities in its code can be safely disclosed publicly.
翻译过来有两层含义:
- Ladybird 尚未发布,仍处于早期开发阶段,因此其代码中的 bug 与漏洞可以安全地公开讨论——这解释了为什么项目把公开 GitHub Issue 作为首选上报渠道,而不是像已上线产品那样强制私密披露。
- 默认建议是把安全问题作为普通 GitHub Issue 报告,并使用仓库中预置的 bug_report.yml 模板(对应政策中给出的
new?template=bug_report.yml链接)。
从该 Issue 模板的字段设计看,一次有效的安全/缺陷报告需要提供:问题摘要(Summary)、操作系统(Linux / macOS / Windows / Android 四选一)、复现步骤、预期与实际行为、最小化测试用例(Reduced test case,模板中特别标注这可能是“你能提供的最重要的东西”)、完整日志输出与 backtrace、截图或录屏,以及非默认构建标志。config.yml 同时保留了空白 Issue 通道与 FAQ、文档、社区入口,方便非模板化的交流。
两条并行的上报渠道
渠道一:公开 GitHub Issue(默认推荐)
适用于绝大多数情况。由于 Ladybird 未发布,公开披露不会造成实际风险,公开 Issue 能让维护者和社区直接参与排查,收敛速度最快。
渠道二:GitHub 私密安全通告流程(Security Advisory)
SECURITY.md 同时说明,仓库上已启用私密漏洞报告功能。如果你发现了 Ladybird 自身的安全问题,或者发现了你认为会波及 Ladybird 的其他浏览器的安全问题,可以按照 GitHub 官方文档中的“创建仓库级安全通告”流程私下报告给维护者。该渠道的处理规则包括:
- 公开披露与编号:通过私密流程被受理的 Issue,在解决后会公开披露,并获得一个安全通告标识符(security advisory identifier);
- 维护者可扩展处置团队:根据所需的专业能力,维护者可以邀请常规贡献者参与处置与解决过程;
- 研究者署名:通过私密流程报告安全问题的研究者,会在安全通告中获得署名致谢(credited in the advisory)。
报告的受理边界与边界外处理
政策中还有两条明确的“管理性”条款:
- 拒绝权:维护者保留拒绝“并非安全问题”或“不在 Ladybird 范围内”的报告的权利。被判定不是安全问题的报告,应改以普通 GitHub Issue 形式重新提交;如果你不愿重新提交,维护者可能会自行代为转成普通 Issue。
- 不提供赏金:Ladybird 目前不提供任何安全问题的 bug bounty(漏洞赏金)。
范围判定:哪些问题当前不算 Ladybird 的安全问题
这是政策中操作性最强的部分。“Scope of Security Issues”一节指出:Web 平台的许多安全特性尚未在 Ladybird 中实现,因此针对“功能不完整”本身的安全报告,可能会被转回普通 Issue。当前明确列出的范围外示例包括:
- 跨站请求伪造(CSRF,Cross-site request forgery)
- 跨站脚本攻击(XSS,Cross-site scripting)
- 内容安全策略违规(CSP violations)
- 跨源 iframe 沙箱化(Cross-origin iframe sandboxing)
维护者保留在项目成熟、安全问题被持续报告的过程中动态修改这份列表的权利。换言之,今天范围外的类别,随着对应安全特性在 Ladybird 中落地,未来都可能变成有效的安全报告方向。
第三方库的责任边界
Ladybird 浏览器的相当大一部分能力依赖第三方库,典型领域包括图片解码、视频解码、国际化(i18n)与 2D 图形。政策对此划定了清晰的边界:
| 问题类型 | 上报对象 |
|---|---|
| 漏洞位于第三方库自身内部 | 报告给该第三方库的维护者;Ladybird 维护者会与其协作解决 |
| 漏洞与第三方库集成到 Ladybird 的方式相关 | 通过与其他安全问题相同的方式上报给 Ladybird |
从仓库源码结构可以印证这一划分:图片解码集中在 LibGfx/ImageFormats 与独立的 Rust 侧图像解码器 LibImageDecoders,媒体管线位于 LibMedia,国际化与字体处理位于 LibUnicode 和 LibGfx/Font。这些模块正是策略中提到的“第三方依赖”在代码层面的落点——判断一个崩溃究竟属于库内部还是集成层,往往需要先定位到这些目录中的实现。
Fuzzing:安全问题最主要的来源渠道
SECURITY.md 特别提醒:如果你的问题是用 fuzzer 发现的,请先到 oss-fuzz(按 label:Proj-serenity 过滤)查询是否已被记录——Ladybird 继承了 SerenityOS 的 oss-fuzz 项目名,历史上登记在 serenity 项目下。
仓库内 Meta/Fuzzers 就是这套模糊测试的完整基础设施,它与 SECURITY.md 的政策形成了闭环:fuzzer 持续产出候选安全问题,维护者按政策流程受理。
Fuzz 目标清单
fuzzers.cmake 定义了当前全部模糊测试目标,覆盖浏览器攻击面中解析不可信输入的关键路径:
set(FUZZER_TARGETS
ASN1
Base64Roundtrip
BMPLoader
GIFLoader
ICOLoader
Js
JsonParser
MatroskaReader
PEM
PNGLoader
RegexECMA262
RSAKeyParsing
TextDecoder
URL
WasmParser
WOFF
XML
)
if (TARGET LibWeb)
list(APPEND FUZZER_TARGETS CSSParser)
endif()
这些目标与 fuzzers.cmake 中声明的库依赖一一对应:Js 依赖 LibJS LibGC,WasmParser 依赖 LibWasm,MatroskaReader 依赖 LibMedia,各图像加载器依赖 LibGfx LibImageDecoders,ASN1/PEM/RSAKeyParsing 依赖 LibCrypto(ASN1 还额外链接 LibTLS)。对照 SECURITY.md 中列出的第三方依赖领域,可见图片解码与媒体容器恰是 fuzz 覆盖最密集的模块。
本地构建与运行
BuildFuzzers.sh 提供三种构建模式,脚本要求 clang(脚本注明需要 clang >= 14):
# 默认:LLVM libFuzzer 模式,输出到 Build/lagom-fuzzers/
./Meta/Fuzzers/BuildFuzzers.sh
./Build/lagom-fuzzers/FuzzSomething
# 无插桩的 standalone 模式:读取单个测试输入(文件名或 stdin)后退出
./Meta/Fuzzers/BuildFuzzers.sh --standalone
./Build/lagom-fuzzers-standalone/Fuzzers/FuzzSomething
# OSS-Fuzz 容器内模式:由 oss-fuzz 构建系统调用
./Meta/Fuzzers/BuildFuzzers.sh --oss-fuzz
从 BuildFuzzers.sh 的源码看,默认模式通过 CMake 预设 Fuzzers 配置到 Build/lagom-fuzzers 目录,并把检测到的 clang 传入 CMAKE_C_COMPILER/CMAKE_CXX_COMPILER;--oss-fuzz 分支则打开 ENABLE_FUZZERS_OSSFUZZ、注入 oss-fuzz 的 $LIB_FUZZING_ENGINE 链接引擎,并把产物拷贝到 $OUT(见 BuildFuzzers.sh)。
Meta/Fuzzers/CMakeLists.txt 揭示了每种模式的插桩差异:
- libFuzzer 模式:目标以
-g -O1 -fsanitize=fuzzer编译(CMakeLists.txt),并且在 CMakeLists.txt 中将 exe/shared/module 三类链接标志统一追加-fsanitize=address——即 Fuzzing 默认同时启用 Address Sanitizer,这正是 README 所说“Fuzzers work best with Address Sanitizer enabled”的落地实现; - oss-fuzz 模式:若存在
${name}.dict词典文件(如仓库中的FuzzJs.dict、FuzzTextDecoder.dict),会复制到FUZZER_DICTIONARY_DIRECTORY供 fuzz 引擎使用(CMakeLists.txt); - standalone 模式:改为编译 EntryShim.cpp 提供普通
main入口,从文件名或 stdin 读取单个输入。
一个 Fuzz 目标的实现样例
以 JavaScript 引擎的 fuzzer FuzzJs.cpp 为例,其入口函数展示了浏览器侧 fuzz 目标的标准写法——把任意字节流当作 JS 源码送入引擎解析并执行:
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* data, size_t size)
{
AK::set_debug_enabled(false);
auto js = StringView(static_cast<unsigned char const*>(data), size);
if (!Utf8View(js).validate())
return 0;
auto source_text = Utf16String::from_utf8_without_validation(js);
auto vm = JS::VM::create();
auto root_execution_context = JS::create_simple_execution_context<JS::GlobalObject>(*vm);
auto& realm = *root_execution_context->realm;
auto parse_result = JS::Script::parse(source_text.utf16_view(), realm);
if (!parse_result.is_error())
(void)vm->run(parse_result.value());
return 0;
}
值得注意的是它先关闭了 debug 断言(set_debug_enabled(false)),并跳过非法 UTF-8 输入,让 fuzzer 的压力集中在 LibJS 解析器与执行器的真实崩溃路径上,而不是被断言消息淹没。
崩溃复现与分析
Meta/Fuzzers/README.md 还给出了与安全报告直接相关的操作细节,研究者按 oss-fuzz 报告复现问题时可以用到:
- 复现崩溃:
MyFuzzer crash-<hash>(fuzzer 会把 crash、slow 等结果文件直接输出到当前目录); - 在 gdb 中复现时需禁用信号处理以看到真实崩溃位置:
run -handle_abrt=0 -handle_segv=0 crash-...; - 查看 libFuzzer 帮助要用
-help=1(--help会被忽略); - UBSan 信息不充分时设置
export UBSAN_OPTIONS=print_stacktrace=1; - 出现 “invalid path to external symbolizer” 警告说明找不到
llvm-symbolizer,通常需要安装对应的 llvm 包。
此外,README 提示给 fuzzer 提供语料(fuzz corpus)能显著提升效果,仓库在 Base/res/html/misc 下维护了 bmp、jpg 等图像测试套件可作输入;并行 fuzz 可传 -jobs=24 -workers=24,压低日志可传 -close_fd_mask=3。
负责任披露:30 天默认时间线
SECURITY.md 的 “Responsible Disclosure” 一节对披露节奏作出承诺:
- 维护者将与安全研究者协作,及时解决安全问题;
- 所有安全问题默认执行 30 天披露时间线;若双方(维护者与报告者)一致认为需要更多时间,该时间线可以延长;
- 整个过程中,维护者会持续向报告者通报进展与解决步骤;
- 若同一安全问题同时上报给了其他浏览器厂商或开源项目,Ladybird 维护者将采用各方中最长的披露时间线,确保所有相关方都有充足时间完成修复。
这条“取最长者”的条款在跨浏览器漏洞(例如同时影响 Ladybird 与主流浏览器引擎的问题)场景下尤为关键,它与上文“发现你认为会波及 Ladybird 的其他浏览器问题也可私密上报”的条款相互配合,构成完整的跨项目协作机制。
小结:政策与仓库机制如何对应
| SECURITY.md 政策条款 | 仓库中的落地机制 |
|---|---|
| 推荐公开 GitHub Issue 上报 | 预置结构化模板 bug_report.yml,强制最小化用例与日志 |
| 支持私密安全通告,解决后公开并署名 | 依托 GitHub 仓库级 Security Advisory 流程,无需仓库内额外设施 |
| 范围外类别(CSRF/XSS/CSP/iframe 沙箱)列表可动态调整 | 对应 Web 平台安全特性尚未在 LibWeb 中完整实现的现状 |
| 第三方库问题上报其自身维护者 | 图片/媒体/国际化模块集中在 LibGfx/ImageFormats、LibImageDecoders、LibMedia、LibUnicode |
| fuzzer 发现先查 oss-fuzz 记录 | Meta/Fuzzers 提供 libFuzzer/standalone/OSS-Fuzz 三模式构建,18 个 fuzz 目标覆盖解析器与引擎 |
| 30 天披露时间线、多方取最长 | 流程性承诺,维护者全程通报进展 |
对于安全研究者而言,Ladybird 的这套政策可以概括为:门槛低(公开即可)、边界清晰(范围列表 + 第三方库责任划分)、工具链完备(自带 fuzz 目标与 ASan 构建)、节奏明确(30 天默认、可协商、跨厂商取最长)。结合 Meta/Fuzzers 的工具链,任何人都可以在本地对 JS 引擎、WASM 解析器、URL、正则、图像与字体等攻击面发起模糊测试,并按政策流程把发现提交给项目。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0626
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00