资讯动态

OSS-Fuzz 基于 Agent 的构建脚本自动生成:用一条命令完成 OSS-Fuzz 项目接入

发布时间:2026/9/23 13:55:46 来源:尧图企业网站定制
测试应用安全质量保障【免费下载链接】oss-fuzzOSS-Fuzz - continuous fuzzing for open source software.项目地址https://gitcode.com/gh_mirrors/os/oss-fuzz点击查看免费下载本篇技术指南聚焦 OSS-Fuzz 生态中一项关键的自动化能力借助 LLM大语言模型驱动的 Agent 自动生成 OSS-Fuzz 所需的构建脚本并结合 CLI 工具实现输入一个 Git 仓库、输出一个完整 OSS-Fuzz 项目的端到端工作流。读完本文你将掌握 Agent 化构建生成的核心算法与四个关键函数、oss-fuzz-generator generate-full命令的完整使用方式以及如何解读三个真实项目libcypher-parser、Yams、Moment生成的构建脚本并理解该方案在 225 个仓库实测中的能力边界与已知局限。背景自动化 OSS-Fuzz 接入的两个核心难题将任意开源项目接入 OSS-Fuzz 并非易事。OSS-Fuzz 要求每个项目提供特定格式的构建脚本该脚本必须运行在 OSS-Fuzz 提供的构建环境即 base-builder 镜像中。由此自动化 OSS-Fuzz 接入的问题天然被拆分成两个部分创建构建脚本为目标项目及其相关的 fuzzing harness模糊测试驱动编写可在 OSS-Fuzz 构建环境中运行的脚本创建 fuzzing harness编写真正调用目标项目 API 的模糊测试入口函数。任何试图自动化 OSS-Fuzz 接入的解决方案都必须同时解决上述两个问题且要能覆盖风格迥异的开源项目。这项工作的关键目标是支撑一个完整的自动化工作流输入一个尚未接入 OSS-Fuzz 的项目仓库如 GitHub 仓库输出一个可用的 OSS-Fuzz 项目——包含可工作的构建脚本和一个或多个 fuzzing harness。更进一步这个工作流必须易于访问和部署让开源维护者能快速利用其能力。作为参考一个标准的 OSS-Fuzz 项目在本仓库中的目录结构通常由三个核心文件组成这也是自动化流程需要产出的目标产物project.yaml项目元数据主页、主仓库地址、语言、fuzzing 引擎列表等例如 projects/example/project.yamlDockerfile基于gcr.io/oss-fuzz-base/base-builder构建环境负责拉取源码并拷贝构建脚本例如 projects/example/Dockerfilebuild.sh在$SRC、$OUT等环境变量约定下编译 fuzz target 并拷贝到$OUT例如 projects/example/build.sh。在此之前OSS-Fuzz-Gen 的精力主要集中在为已有 OSS-Fuzz 项目生成 fuzzing harness。此前一篇博客文章虽然记录了一种端到端的 OSS-Fuzz 接入方法但其构建脚本生成基于模板策略在应对多样化项目时存在明显局限。为此本文介绍两项改进一种Agent 化的 LLM 构建脚本生成方法一个易于访问和运行的 CLI 工具。总览与示例运行方案的核心目标是仅通过输入一个或多个 Git 仓库就自动化地完整生成 OSS-Fuzz 项目并输出一个或多个 OSS-Fuzz 接入集成。这些能力被打包为一个 Python 包并以 CLI 形式暴露安装和运行都很简单。以下示例为https://github.com/zserge/jsmn生成包含 fuzzing harness 的完整 OSS-Fuzz 项目# Prepare virtual environment python3.11 -m virtualenv .venv . .venv/bin/activate # Clone OSS-Fuzz-gen git clone https://github.com/google/oss-fuzz-gen cd oss-fuzz-gen # Install OSS-Fuzz-gen python3 -m pip install . # Generate fuzzers for https://github.com/zserge/jsmn echo https://github.com/zserge/jsmn input.txt # Run the generation # Setup Vertex AI access: 参见 OSS-Fuzz-Gen 仓库 USAGE.md 中的 LLM access 章节 oss-fuzz-generator generate-full -i input.txt -m vertex_ai_gemini-2-flash-chat --agent -w work-1 # List the files of generated project $ ls final-oss-fuzz-projects/jsmn-agent/ build.sh Dockerfile empty-fuzzer.0.c empty-fuzzer.1.c project.yaml整个流程的第一步是安装 Python 包。目前的做法是先克隆 OSS-Fuzz-Gen 仓库再用python -m pip install .安装。安装后的包内置了一个oss-fuzz-generatorCLI 工具对外暴露 OSS-Fuzz 项目生成能力。随后只需配置好 LLM 运行环境如 Vertex AI然后调用generate-full命令即可。该命令会一次性完成构建脚本生成、fuzzing harness 生成并将所有成功的 fuzzing harness 合并进一个 OSS-Fuzz 项目。具体来说oss-fuzz-generator generate-full会针对input.txt中列出的每个仓库依次执行三个步骤生成一个能够编译该项目 fuzzers 的构建脚本如果第 1 步成功则为项目生成fuzzing harness将成功的 fuzzing harness合并为一个完整的 OSS-Fuzz 项目。本文后续将聚焦第 1 步——Agent 化的构建脚本生成。从生成的产物可以看到Agent 产出的项目结构与 OSS-Fuzz 仓库中真实项目的形态完全一致build.sh、Dockerfile、project.yaml加 fuzzing harness 源文件。你可以对照本仓库中的 projects/example 目录理解这些产物的标准形态例如 projects/example/build.sh 展示了find批量拷贝 fuzzer 到$OUT的写法而 projects/example/my-api-repo/do_stuff_fuzzer.cpp 展示了一个标准LLVMFuzzerTestOneInput入口的实现。Agent 化构建脚本生成的算法原理Agent 化构建脚本生成依赖三个核心组件初始提示词initial prompt向 LLM 概述为任意仓库编写构建脚本的总体任务与约束Agent 执行器负责与 LLM 通信并在构建脚本将要运行的运行时环境中执行 LLM 提供的任意命令使 LLM 能够探索运行时环境构建与运行回灌流程负责运行生成的构建脚本、执行生成的 fuzzer用真实运行结果引导 LLM 的下一步输出。Agent 化构建生成的总体算法如下initial_prompt prepare_initial_prompt(target_repository) prompt prepare_initial_prompt(target_repository) llm_client llm_start_chat() while should_keep_going(): llm_response llm_client.chat(prompt) res parse_llm_response(llm_response) if res.is_commands() { output execute_commands(res.get_commands()); } else if (res.has_build_script()) { output build_and_run_fuzzer(res.get_build_script(), res.get_fuzz_harness()); if (output.has_successful_build_script()) { // Success in harness generation return output } } else { // Failure happened in parsing LLM output exit() } // Prepare a next prompt for the LLM to chat. prompt prepare_next_prompt(output);当算法执行到return output这一行时即认为构建脚本生成成功。这一行只有在 LLM 创建的构建脚本附带一个 fuzz harness并且该 harness 能够成功编译、链接到目标仓库代码时才会到达。算法中有四个关键函数parse_llm_response接收 LLM 返回的原始文本将其转换为两类结果之一(1) 需要在构建 fuzzer 的运行时环境中执行的一组命令(2) 一个构建脚本及其携带的 fuzzing harness 源码。prepare_initial_prompt会事先指示 LLM 以某种标准格式输出例如用 XML 标签包裹输出以便可靠解析execute_commands当parse_llm_response判定 LLM 返回的是命令列表时此函数在构建脚本将要运行的运行时环境中执行这些命令。核心价值在于让 LLM 能够探索、理解并测试运行时环境命令执行结果会返回给 LLM由于 Agent 运行在循环中LLM 可以持续下发命令、解读输出并据此行动build_and_run_fuzzer当parse_llm_response判定 LLM 返回的是构建脚本可能附带 fuzzing harness也可能为空时此函数在运行时环境中构建这些产物。构建输出会被分析若成功构建出 harness则流程结束若构建失败则构建脚本的执行输出会被保存并最终回传给 LLMprepare_next_prompt当本轮迭代未产生成功构建脚本时可能是 LLM 返回了命令列表也可能是构建脚本构建失败该函数用execute_commands和build_and_run_fuzzer的输出构造下一轮提示词。提示词以轻量文本描述包裹运行输出作为下一轮 Agent 迭代的输入传给llm_client.chat。算法成功时输出的构建脚本将成为 OSS-Fuzz 项目的基础随后即可复用 OSS-Fuzz-Gen 的核心能力为该项目生成 fuzzing harness。从算法可以看出Agent 的核心优势在于它拥有执行权限——可以在真实运行时环境中运行命令、安装依赖、修改源码观察输出然后不断迭代。这与纯模板化方案有本质区别模板只能覆盖已知模式而 Agent 可以针对每个项目的特殊情况临场发挥。实测评估225 个仓库、88 个有效集成为验证该方案研究团队在一批 C/C 编写的 GitHub 仓库上运行了这套流程共分析225 个仓库产出了88 个带有效构建脚本的 OSS-Fuzz 集成。随后团队还使用 OSS-Fuzz-Gen 的 harness 生成能力在这些项目上运行以确认构建脚本的有效性。实测发现该方案有许多长处它克服了众多项目设置的障碍能够创建模板化方案无法生成的构建脚本。下面通过三个真实样例来展示其能力边界。案例一libcypher-parser目标仓库https://github.com/cleishm/libcypher-parser生成的构建脚本如下# Build script for libcypher-parser with fuzzing harness # Install necessary dependencies apt-get update apt-get install -y make autoconf automake libtool curl # Install autoconf 2.71 cd /tmp curl -O http://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz tar -xzf autoconf-2.71.tar.gz cd autoconf-2.71 ./configure make make install # Install leg tool cd /tmp curl -L -O https://www.piumarta.com/software/peg/peg-0.1.18.tar.gz tar -xzf peg-0.1.18.tar.gz cd peg-0.1.18 make make install # Build libcypher-parser cd $SRC/libcypher-parser ./autogen.sh ./configure --enable-static --disable-shared make # Copy the static library to the output directory cp lib/src/.libs/libcypher-parser.a $OUT/ # Compile the fuzzing harness for fuzzer in $(find $SRC -maxdepth 1 -name empty-fuzzer.*); do fuzzer_basename$(basename $fuzzer .c) $CC $CFLAGS -I$SRC/libcypher-parser/lib/src $fuzzer -o $OUT/${fuzzer_basename} \ -L$OUT -lcypher-parser -Wl,--whole-archive $LIB_FUZZING_ENGINE -Wl,--no-whole-archive done总体而言这是一个相当复杂的构建它安装了与运行时环境自带版本不同的 autoconf还额外安装了一个名为 peg 的工具。为了识别出 leg/peg 工具的必要性Agent 必须先尝试在缺少该工具的情况下构建项目并解读构建输出——因为缺少 peg 时配置 libcypher-parser 会报出如下错误... checking for leg... no configure: error: leg is required: please install http://piumarta.com/software/peg/ ERROR:__main__:Building fuzzers failed.这正是execute_commands 循环迭代机制价值的直接体现Agent 通过构建 → 读报错 → 安装依赖 → 重新构建的闭环自行推断出了依赖关系。脚本还展示了两个值得注意的细节$CC、$CFLAGS、$LIB_FUZZING_ENGINE是 OSS-Fuzz 构建环境注入的关键变量$LIB_FUZZING_ENGINE提供 fuzzing 引擎的链接库脚本用for循环遍历$SRC下所有empty-fuzzer.*文件并逐一编译从而支持任意数量的 fuzzing harness——这是后文将提到的设计约束之一。案例二Yams目标仓库https://github.com/jpsim/Yams生成的构建脚本如下#!/bin/bash # Set up build environment cd $SRC/Yams/Sources/CYaml mkdir -p build cd build cmake .. -DCMAKE_C_COMPILER$CC -DCMAKE_CXX_COMPILER$CXX make # Compile the fuzzing harness $CC $CFLAGS -I$SRC/Yams/Sources/CYaml/include -I$SRC $SRC/empty-fuzzer.c -o $OUT/empty-fuzzer -L. -Wl,--whole-archive libCYaml.a -Wl,--no-whole-archive $LIB_FUZZING_ENGINE这是一个简单的 cmake 构建脚本但它在 cmake 命令中传入了-DCMAKE_C_COMPILER$CC -DCMAKE_CXX_COMPILER$CXX确保目标项目使用 OSS-Fuzz 运行时环境指定的编译器即带 sanitizer 和覆盖率插桩的 clang进行构建——这是 OSS-Fuzz 构建的关键要求否则插桩不会生效。有趣的是这里 fuzz harness 的编译链接没有使用循环。这在原理上可行项目能构建并链接一个 fuzzing harness但存在局限它无法构建和链接任意数量的 fuzzing harness。案例三Moment目标仓库https://github.com/kmussel/Moment这是一个已停止维护约 10 年的库构建这样一个老旧项目具有特殊挑战。生成的构建脚本如下#!/bin/bash # Install necessary tools apt-get update apt-get install -y bison flex # Set source and output directories SRC_DIR$SRC/Moment OUT_DIR$OUT # Preprocess parseIt.ym to remove the Foundation import sed /#import Foundation\/Foundation.h/d $SRC_DIR/parseIt.ym $SRC_DIR/parseIt_preprocessed.ym # Use bison to generate parseIt.c and y.tab.h bison -d -o $SRC_DIR/parseIt.c $SRC_DIR/parseIt_preprocessed.ym # Rename the generated header to y.tab.h mv $SRC_DIR/parseIt.h $SRC_DIR/y.tab.h # Use flex to generate tokeIt.c flex -o $SRC_DIR/tokeIt.c $SRC_DIR/tokeIt.l # Compile the source files into object files $CC $CFLAGS -c $SRC_DIR/TimeParser.c -o TimeParser.o $CC $CFLAGS -c $SRC_DIR/parseIt.c -o parseIt.o $CC $CFLAGS -I$SRC_DIR -c $SRC_DIR/tokeIt.c -o tokeIt.o # Archive the object files into a static library llvm-ar rcs libmoment.a TimeParser.o parseIt.o tokeIt.o # Compile the fuzzing harness and link with the static library $CC $CFLAGS -I$SRC_DIR $SRC/empty-fuzzer.c -o $OUT_DIR/empty-fuzzer -L. libmoment.a $LIB_FUZZING_ENGINE与 libcypher-parser 类似这个构建脚本令人印象深刻的地方在于其复杂性下载并安装自定义软件包bison、flex并将这些工具作为构建过程的一部分使用。脚本还用sed修改了目标项目中的源文件移除不适用于当前环境的#import Foundation/Foundation.h并运行 bison 和 flex 生成编译所需的代码。此外该项目自身没有任何构建系统文件如Makefile因此 Agent 退而求其次直接逐个编译源文件并用llvm-ar打包静态库——这种无构建系统也能接的能力是模板方案很难覆盖的。值得一提的是OSS-Fuzz 运行环境中的$SRC、$OUT、$CC、$CFLAGS、$LIB_FUZZING_ENGINE等环境变量是整个构建脚本契约的核心本仓库的 projects/example/build.sh 和 projects/example/Dockerfile 中可以看到这些约定的标准用法。新项目接入的完整流程与规范可参考仓库根目录的 new_project_guide.md。局限性与未来工作在实测评估过程中研究团队观察到若干局限和可改进之处。构建脚本成功却绕过了目标源码团队观察到若干案例Agent 生成的构建脚本完全绕过了目标源码的编译最终只是构建了一个空 fuzzing harness。问题在于当前方案不会对生成的 harness 做后处理分析以验证目标源码是否真正进入了最终二进制文件。这意味着当流程推进到 harness 生成阶段时由于构建脚本没有涉及任何目标源码的编译无法支撑后续工作流。虽然这种情况比较少见但必须的解决方案是对生成的构建脚本做更严格的后处理完整性校验或者在端到端工作流中提供后续修正能力。只能构建单个 fuzzing harness 的脚本方案会指示 LLM 生成能够构建任意数量fuzzing harness 的构建脚本以便复用该脚本编译 OSS-Fuzz-Gen 在 harness 生成阶段产出的所有 harness很可能不止一个。但实测发现这一约束并不总是被遵守部分构建脚本最终只能构建单个 fuzzing harness例如构建指令中缺少循环。此时用户需要手动修改构建脚本使其能够构建任意数量的 harness才能支撑最终需要两个及以上 harness 的 OSS-Fuzz 接入。融入目标代码库的构建系统当前方案产出的构建脚本通常显式使用CC/CXX环境变量将 fuzzing harness 链接到脚本前面阶段构建的静态库上即由一组命令 一份 harness 源码组成。另一种思路是把 fuzzer 的构建融入目标仓库自身的构建系统如扩展其 Makefile这样虽然没有实质性的功能差异但对开发者更友好、更易维护。失败生成的诊断与结论当构建脚本生成失败时目前没有任何关于失败原因的解释。一个自然的扩展方向是引入另一个 Agent 或类似机制专门分析构建失败的原因。例如区分失败原因是硬性原因如目标代码在相关构建运行时中根本无法编译还是 LLM 能力不足没能找到合适的方案。如果是硬性原因反而是一个有价值的结论——可以明确告知用户目标项目不兼容 OSS-Fuzz例如 Windows-only 项目。结论本文介绍了 OSS-Fuzz-Gen 的一项新能力通过Agent 化构建脚本生成从零开始产出 OSS-Fuzz 项目集成。该能力以 CLI 工具形式提供只需一条命令即可生成一个 OSS-Fuzz 项目。研究团队在 225 个 C/C 项目上进行了实测得到 88 个有效的 OSS-Fuzz 构建脚本并通过若干案例展示了能力亮点同时识别了局限与未来方向。整体来看这套 Agent 化方案把接入 OSS-Fuzz从一件依赖人工经验的手工活变成了可规模化、可复现的自动化流程。它与 OSS-Fuzz 仓库中的其他自动化探索一脉相承——例如引入 Agent 能力的博客文章展示了 CLI Agent 如何在 OSS-Fuzz 仓库中直接完成新项目接入、覆盖率改进、构建修复等任务LLM 合成 harness 的博客文章则记录了更早期的端到端接入方案。构建脚本生成与 harness 生成这两条技术线互相配合正逐步逼近任何项目都能一键接入 OSS-Fuzz的目标。如果你希望在自己的项目上尝试这套工具只需按文中示例安装 OSS-Fuzz-Gen、配置 LLM 访问然后运行oss-fuzz-generator generate-full。如果遇到构建生成不工作的情况建议将该信息反馈给 OSS-Fuzz-Gen 项目维护者帮助持续改进这一自动化能力。赞分享测试应用安全质量保障【免费下载链接】oss-fuzzOSS-Fuzz - continuous fuzzing for open source software.项目地址https://gitcode.com/gh_mirrors/os/oss-fuzz点击查看免费下载相关推荐OSS-Fuzz 中的 LLM 驱动 Fuzz Harness 合成为未接入项目自动生成 OSS-Fuzz 集成OSS Fuzz 中的 LLM 驱动 Fuzz Harness 合成为未接入项目自动生成 OSS Fuzz 集成 OSS Fuzz 团队在其 OSS Fuzz测试应用安全质量保障OSS-Fuzz Java/JVM 项目接入指南基于 Jazzer 的 fuzz target 编写与构建OSS Fuzz Java/JVM 项目接入指南基于 Jazzer 的 fuzz target 编写与构建 OSS Fuzz 对 Java 及任何运行在 JV测试应用安全质量保障OSS-Fuzz Go 项目集成指南从 go-fuzz 到原生 Go 1.18 Fuzzing 的完整接入流程OSS Fuzz Go 项目集成指南从 go fuzz 到原生 Go 1.18 Fuzzing 的完整接入流程 本文是 OSS Fuzz 新项目接入指南 d测试应用安全质量保障上一篇DeepChat Tape Trace Inspector会话级只读执行检查器的完整实现方案下一篇CANN/HCOMM带通知非阻塞写操作创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价