国内做开源项目或者企业内部代码库维护的同学,这两年应该都有一个明显感受:代码量越来越大,漏洞扫描工具越来越贵,单靠人肉看代码做安全审计,效率已经跟不上了。大模型辅助代码审计,逐渐从“试水”走向“日常工具”。本文将围绕 Open source 项目在使用 GLM-5.3 进行代码审计时的完整流程展开,包含模型选型、审计策略设计、嵌入式场景下的实际案例,以及我在审计过程中遇到的两个典型编译问题(arm_acle.h 与 core_cm0plus.h 缺失)的排查思路。无论你是做应用开发、嵌入式开发,还是负责团队安全建设,都可以把这套流程直接搬到你自己的项目里。
1. 背景与核心概念
1.1 开源代码审计为什么需要大模型
代码审计这个词,过去一般出现在安全团队的工作清单里。传统流程是人工阅读源代码,结合 SAST 工具(比如 Fortify、SonarQube、Semgrep)扫一遍,再对告警结果做人工研判。这个流程的问题很现实:SAST 工具误报率高,人工研判耗时;而很多历史项目、二次开发项目、甚至从 GitHub 上拉下来的开源组件,根本没有精力做全量审计。
GLM-5.3 这类大模型介入后,整个流程发生了两个重要变化:
第一,自然语言交互降低了审计门槛。过去你至少要会用正则表达式、理解 AST 语法树,才能写出像样的扫描规则。现在你可以直接对模型说“请检查这段 C 代码里是否存在内存越界风险”,模型能理解上下文并给出分析。
第二,上下文理解弥补了工具误报问题。SAST 工具经常不理解业务逻辑,不知道某个变量在业务中不可能为负数。GLM-5.3 能结合代码上下文、函数调用关系、数据流方向,给出更接近“人”的判断。
但这里必须强调:大模型不能替代人工审计。它的定位是“辅助研判”,能帮你把 10000 行代码快速缩小到 100 行重点区域。最终的安全决策和修复动作,必须由有经验的开发或安全人员把关。
1.2 GLM-5.3 在审计链路中的角色
GLM-5.3 是智谱 AI 推出的大语言模型系列。在实际开源项目审计中,它主要承担三个角色:
- 代码审查助手:理解代码片段,指出潜在的越界、空指针、未初始化、日志泄露等风险。
- 文档与报告生成器:将杂乱的项目情况整理为规范的审计报告、修复建议、依赖清单。
- 多人协作的“翻译官”:把安全团队的问题转化为开发团队能理解的修复语言,反之亦然。
实际使用中,我通常会把 GLM-5.3 和 GLM-5.3-Flash 配合使用。GLM-5.3 处理复杂逻辑和关键代码段,GLM-5.3-Flash 则用来做批量化的快速筛查和格式化输出。后面会有具体的分工说明。
1.3 本文的适用场景
这篇文章并不是一篇纯讲“AI 有多强”的科普文,而是一篇可以跟着操作的工程笔记。我会围绕一次真实的开源项目审计过程来展开:
- 对开源嵌入式项目进行代码安全审计;
- 构建系统遇到
arm_acle.h缺失和core_cm0plus.h缺失问题; - 用 GLM-5.3 辅助分析报错根因和修复方案;
- 输出规范的审计报告和修复建议。
读者对象包括:嵌入式开发者、开源项目维护者、DevSecOps 工程师、以及对大模型辅助开发感兴趣的同学。
2. 环境准备与版本说明
2.1 模型版本选择
本次实操涉及两个模型版本:
| 模型 | 定位 | 适用任务 |
|---|---|---|
| GLM-5.3 | 通用旗舰版本,上下文能力强,逻辑推理深 | 核心代码审计、复杂报错根因分析、报告审查 |
| GLM-5.3-Flash | 轻量快速版本,响应速度快,成本更低 | 批量代码预筛选、依赖关系梳理、格式化输出 |
需要注意,不同版本的模型在不同平台的调用方式可能略有差异。如果你使用的是智谱开放平台 API,接入时建议先查阅最新的接口文档,确认模型名称、token 限制和计费规则。本文重点展示流程与思路,具体参数以你实际使用的平台为准。
2.2 审计项目环境信息
为了便于演示,我设计一个典型场景:
- 项目类型:基于 ARM Cortex-M0+ 的嵌入式开源项目(例如某个传感器驱动或 IoT 设备固件工程)
- 开发环境:Keil MDK 或兼容 ARMCC 的工具链
- 编程语言:C
- 核心模块:硬件抽象层(HAL)、启动文件、外设驱动
- 审计目标:发现导致编译失败的环境问题,同时检查代码中的安全缺陷
实际项目千差万别,但审计方法论是一致的。你可以把本文的项目替换为你手头的任意开源项目。
2.3 推荐的项目目录结构
为了让 GLM-5.3 更高效地理解项目,建议在审计前把项目整理成清晰的目录结构:
project-root/ ├── src/ # 源码目录 ├── inc/ # 头文件目录 ├── drivers/ # 驱动模块 ├── startup/ # 启动文件(含 CMSIS / 芯片 SDK 相关头文件) ├── build/ # 编译输出目录 ├── docs/ # 项目文档 └── audit/ # 审计过程文件(建议新建)在audit目录下,我一般会放三个文件:
file_list.txt:待审计文件清单prompt_templates.md:各类审计 prompt 模板audit_report.md:最终审计报告
这样做的原因是,大模型处理大量源码时,如果一次性全部贴入,效果往往不好。更有效的做法是“分模块 + 明确任务 + 逐步提问”。
3. 核心策略:如何用 GLM-5.3 做开源代码审计
3.1 审计流程总览
用 GLM-5.3 做代码审计,并不是简单地把代码复制给模型然后问“有没有漏洞”。一套完整的流程应该是:
- 项目摸底:整理目录结构,统计文件清单,标注重点关注模块。
- 预处理筛选:用 GLM-5.3-Flash 对文件做批量初筛,找出可疑片段。
- 深度审计:将筛选出的重点文件交给 GLM-5.3 做深度分析。
- 交叉验证:将模型发现的问题与人工判断、静态扫描工具结果比对。
- 报告输出:由模型生成标准格式的审计报告,人工审核后发布。
3.2 编写高效的审计 Prompt
这里我不推荐用“帮我看看这段代码有什么问题”这种宽泛的提问方式。效果更好的 prompt 通常包含四个要素:角色设定、任务描述、约束条件、输出格式。
下面是一个我经常使用的模板:
你是一名资深的安全审计专家。下面是一段 C 语言代码,来自某个嵌入式开源项目。 请从以下角度分析: 1. 是否存在缓冲区溢出或内存越界风险; 2. 是否存在空指针解引用; 3. 是否存在不安全的外部输入处理; 4. 是否存在资源泄露(如未关闭的外设、未释放的内存); 5. 代码风格与可维护性问题(简要说明)。 输出格式: - 风险等级:高 / 中 / 低 - 问题位置:文件 + 行号 - 问题描述:用通俗语言说明触发场景 - 修复建议:给出具体修复思路,必要时提供代码片段 请基于代码事实分析,不确定的地方请明确说明“需要进一步确认”。这样的 prompt 能显著降低模型“泛泛而谈”的概率。GLM-5.3 在明确输出格式后,返回的结果更结构化,也更便于直接粘贴进审计报告。
3.3 借助 GLM-5.3-Flash 做批量预筛选
很多开源项目动辄几百个源文件,全部丢给 GLM-5.3 做深度分析,费用和时间都不太划算。更合理的做法是:先用 GLM-5.3-Flash 做第一遍粗筛。
例如,审计目标如果是“找出项目中所有外部输入点”,我通常的处理方式:
- 先让 GLM-5.3-Flash 帮我把项目源文件中的
scanf、recv、read、memcpy、strcpy、sprintf等高风险函数调用点全部列出来。 - 再把输出的高风险文件清单交给 GLM-5.3 做深入分析。
- 粗筛阶段不追求分析深度,只追求“不要漏”。
这种大小模型配合的方式,是实际工程中性价比最高的组合。
3.4 人工研判不可省略
这里必须泼一盆冷水。无论 GLM-5.3 分析得多细致,它仍然可能产生“幻觉”——即给出不存在的漏洞、错误的行号、甚至编造修复方案。这些错误在安全场景中是非常危险的。
所以我的铁律是:
- 模型给出的每一个“高危问题”,都必须人工打开代码进行二次确认;
- 修复代码上线前,必须经过编译验证和功能测试;
- 涉及安全补丁的发布,需要由安全负责人签字确认。
GLM-5.3 的价值是“把 1000 个待检查点缩小到 10 个”,而不是“替你直接确认那 10 个点”。
4. 实战:嵌入式开源项目的审计过程
下面我们进入完整实战环节。为了方便演示,假设我们审计的是一个基于 ARM Cortex-M0+ 的开源 IoT 项目,使用 CMSIS(Cortex Microcontroller Software Interface Standard)库。
4.1 项目创建与结构整理
首先,在本地克隆开源项目并整理目录。这里以命令行为例:
git clone https://example.com/your-open-source-project.git cd your-open-source-project mkdir audit find . -name "*.c" -o -name "*.h" > audit/file_list.txt wc -l audit/file_list.txtfile_list.txt生成后,建议先人工浏览一遍,剔除第三方库目录(比如lib/或者vendor/),重点审计项目自身的业务代码。
4.2 编译项目并记录报错
审计的第一步不是直接看代码,而是先把项目编译起来。一个连编译都不过的项目,先别提什么安全审计。这里我用 Keil MDK 或者其他 ARM 编译器环境来编译:
# 假设项目使用 makefile 构建 make clean make很快我发现编译中断,出现了两个典型的报错:
error: #5: cannot open source input file "arm_acle.h": no such file or directory fatal error[pe1696]: cannot open source file "core_cm0plus.h"这两个报错在嵌入式开发中非常典型。我把它们交给 GLM-5.3 分析,得到的初步判断是:
arm_acle.h属于 ARM Compiler 提供的 ACLE(Arm C Language Extensions)头文件。如果编译器路径配置不正确,或者使用了不兼容的工具链版本,就可能找不到它。core_cm0plus.h是 CMSIS 中针对 Cortex-M0+ 内核定义的头文件。这个文件缺失一般意味着 CMSIS 库路径没有被正确添加到工程包含路径中,或者 CMSIS 版本不匹配。
4.3 使用 GLM-5.3 分析编译错误的根因
把完整的报错信息、工程目录结构、编译器版本信息整理后,我向 GLM-5.3 发起如下提问:
我使用的编译器是 ARMCC(Keil MDK 环境),目标芯片是 Cortex-M0+。编译时提示: error: #5: cannot open source input file "arm_acle.h": no such file or directory fatal error[pe1696]: cannot open source file "core_cm0plus.h" 工程中已经包含了 CMSIS 文件夹,但依然报错。 请给出排查步骤,按优先级排列,并说明每步的作用。GLM-5.3 给出的分析方向如下:
- 检查
arm_acle.h是否真的存在于编译器的内置 include 目录中。 - 检查
core_cm0plus.h是否存在工程内的 CMSIS/Core/Include 目录。 - 检查 Keil MDK 的 C/C++ 编译选项里的 Include Paths 是否覆盖了 CMSIS 目录。
- 检查是否定义了正确的器件型号宏(如
STM32F0XX、NRF52832_XXAA等),因为某些头文件依赖宏定义做条件编译。 - 检查编译器版本是否过旧,因为
arm_acle.h是从某个 ARMCC 版本开始才正式提供的。
这个判断让我少走了很多弯路。
4.4 手动验证与修复
根据 GLM-5.3 的分析,我实际动手验证。
首先,确认arm_acle.h是否存在:
# 在 Keil 安装目录中搜索该头文件 find /opt/keil -name "arm_acle.h"如果没有找到,说明当前编译器版本可能较旧,或者安装不完整。如果找到了,但编译仍报错,则大概率是include path 没有配置。
其次,确认core_cm0plus.h的位置:
find . -name "core_cm0plus.h"如果项目目录中找不到,则说明 CMSIS 库没有完整放入工程。需要去官网下载对应芯片厂商的 CMSIS 包,或者从其他同系列项目中复制。
修复方式示例(在 Keil MDK 中,通过菜单 Options for Target -> C/C++ -> Include Paths 添加路径):
../Libraries/CMSIS/Include ../Libraries/CMSIS/Device/ST/STM32F0xx/Include这里有一个易被忽略的细节:头文件搜索顺序。即使路径配置正确,如果多个版本的 CMSIS 存在于不同目录,编译器可能包含到旧版本的头文件,导致功能宏不匹配。建议在配置 include path 时,把芯片厂商专用目录放在通用 CMSIS 目录之前。
4.5 用 GLM-5.3-Flash 批量提取可疑代码
编译问题解决后,我们回到正式审计任务。我写了一个简单的 Prompt 模板,让 GLM-5.3-Flash 处理批量筛查:
你是代码审计预筛助手。请阅读以下源码文件片段,识别所有可能导致安全问题的函数调用,包括但不限于: - memcpy / strcpy / sprintf 等无边界复制函数 - 对数组下标的直接赋值操作 - 对用户输入的校验缺失 - 外设寄存器异常赋值 输出格式为表格: | 文件 | 行号 | 函数 | 风险类型 |将待审计的 C 文件分批传入,得到一张风险点位表。这张表不需要 100% 准确,它的作用是帮我把审计注意力快速集中起来。
4.6 核心代码深审:内存拷贝漏洞案例
在某一个驱动文件中,GLM-5.3 发现了一个典型问题。原代码大致如下:
// 文件路径:drivers/sensor_hal.c int sensor_hal_read(uint8_t *buf, uint16_t len) { uint8_t tmp[32]; if (len > 0) { memcpy(tmp, buf, len); // 缺少长度上限检查 } // 处理 tmp 数据... return 0; }我请 GLM-5.3 做深度分析,它给出的意见是:
- 风险等级:高
- 问题位置:sensor_hal.c 中
memcpy调用 - 问题描述:
len来自函数入参,调用方传入的值可能大于tmp数组长度 32,导致栈缓冲区溢出。嵌入式系统通常没有完整的内存保护机制,这种漏洞可能导致固件崩溃或被利用执行任意代码。 - 修复建议:拷贝前必须校验
len <= sizeof(tmp)。
修复后的代码:
int sensor_hal_read(uint8_t *buf, uint16_t len) { uint8_t tmp[32]; if (len > sizeof(tmp)) { return -1; // 参数校验失败 } memcpy(tmp, buf, len); // 处理 tmp 数据... return 0; }这个案例非常简单,但在嵌入式开源项目中出现频率极高,值得作为审计样例反复讲解。
4.7 生成审计报告
所有问题确认后,让 GLM-5.3 生成标准格式的审计报告。下面是报告片段的示例:
# 审计报告:example-iot-project 审计日期:2025-XX-XX 审计工具:GLM-5.3 + 人工复核 项目范围:src/、drivers/ 目录下共 23 个 C 文件,11 个头文件 ## 发现的问题汇总 | 编号 | 文件 | 风险等级 | 问题描述 | 状态 | | --- | --- | --- | --- | --- | | 1 | drivers/sensor_hal.c | 高 | 栈缓冲区溢出风险 | 已修复 | | 2 | src/main.c | 中 | 条件编译中未定义宏可能导致代码分支错误 | 待确认 | | 3 | startup/startup.s | 低 | 启动文件栈大小配置偏小 | 建议调整 | ## 风险统计 - 高危:1 个 - 中危:1 个 - 低危:1 个注意:报告必须由人工复核后才算完成。机器生成报告字段再规范,也不能代替最终负责人签名。
5. 常见问题与排查思路
在本次审计过程中,除了目标项目发现的问题,审计工具自身和使用流程中也有不少容易踩的坑。这里整理成表格。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| GLM-5.3 返回异常行号或错误文件 | 模型对超长上下文的定位能力有限 | 分片传入代码,同时人工核对行号 |
| GLM-5.3 虚构并不存在的漏洞 | 上下文不足,模型进行了“猜测” | 必须提供完整上下文,并让模型标注“不确定”之处 |
| 批量筛查时 token 消耗过高 | Prompt 设计不合理,重复传入了大段无用内容 | 先精简代码,去掉注释和无关注释行再传入 |
| 模型混淆 CMSIS 版本差异 | 不同芯片厂家的 CMSIS 实现有差异 | 人为补充芯片型号和 SDK 版本信息 |
| API 调用超时 | 单次请求内容过长 | 拆分文件,限制单次输入的代码量 |
下面详细说一下热词中提到的两个编译问题。
5.1error: #5: cannot open source input file "arm_acle.h"
这个错误的字面意思是编译器找不到arm_acle.h。arm_acle.h是 ARM 编译器提供的 ACLE 相关头文件,用来支持一些 ARM 扩展指令的内建函数,例如某些 DSP 指令或数据一致性操作。
排查顺序:
- 检查编译器安装完整性。重新执行安装程序,或者查看编译器根目录下的
include文件夹中是否存在该文件。 - 检查编译选项。某些工程启用了
--c99或--gnu扩展,而对应的头文件路径未被加入。 - 检查头文件宏依赖。如果代码中通过
#ifdef __ARM_ACLE条件包含该头文件,需要确认编译器是否定义了对应宏。 - 检查芯片支持包。某些芯片 SDK 中会引用
arm_acle.h,但 SDK 与编译器版本不匹配。
解决方案示例(Makefile 中增加 include 路径):
CFLAGS += -I$(ARM_COMPILER_PATH)/include5.2fatal error[pe1696]: cannot open source file "core_cm0plus.h"
core_cm0plus.h是 CMSIS 中针对 Cortex-M0+ 内核的头文件。这个文件缺失,通常是因为工程中根本没有引入 CMSIS 核心支持库,或者路径未正确配置。
排查顺序:
- 检查工程目录下是否存在
CMSIS/Core/Include/core_cm0plus.h。如果不存在,需要从 CMSIS 官方包或芯片厂商 SDK 中导入。 - 检查 Keil MDK 的 Run-Time Environment 是否勾选了 CMSIS-CORE 支持。
- 检查 include path 是否正确指向 CMSIS Core Include 目录。
- 确认工程定义的目标器件是 Cortex-M0+ 系列,避免在 M3/M4 工程中错误包含
core_cm0plus.h。
处理方式:
Options for Target -> C/C++ -> Include Paths 添加:C:\Keil_v5\ARM\PACK\ARM\CMSIS\5.9.0\CMSIS\Core\Include如果使用 GCC 工具链,则对应:
CFLAGS += -I$(CMSIS_PATH)/CMSIS/Core/Include之所以把这两个错误单列出来,是因为它们几乎是每个嵌入式开源项目迁移到新环境时的“第一道鬼门关”。在审计报告里,这类环境问题也应当记录,因为它会影响后续所有静态分析和编译验证工作。
6. 最佳实践与工程建议
6.1 审计流程的工程化建议
- 先构建工具链,再启动审计。代码审计不是纯文字工作,必须以“可编译、可运行”为前提。审计开始前,先确保项目能编译出固件或可执行文件。
- 静态扫描、模型研判、人工复核三层结合。GLM-5.3 可以辅助研判,但它不该是第一道防线。先用低成本静态扫描工具筛一遍,再让模型做语义分析,最后由人拍板。
- 每次提问都要求模型输出“依据”。在 prompt 中明确要求“请引用代码中的具体行号和变量名”,能显著减少模型胡编乱造的概率。
- 对嵌入式项目,特别注意缓冲区边界。栈空间有限,任何无界复制都可能是致命的。与此相关的还有中断服务程序中的共享变量访问,需要标注
volatile并考虑原子性。
6.2 安全底线
- 不要在公开场景上传带有敏感信息的私有代码。如果项目是公司私有库,请使用私有化部署或企业内部网关。
- 模型输出的修复建议不能直接合入生产环境。必须经过测试,特别是嵌入式代码,需要做硬件验证。
- 审计报告中如涉及高危漏洞,应在修复并验证后再对外公开。开源项目维护者尤其要注意,不要在漏洞修复尚未发布时就公开报告细节,以免被恶意利用。
6.3 针对嵌入式 Open Source 项目的额外建议
下面是几条实测有效的工程建议:
- 始终锁定编译器版本和 CMSIS 版本,避免因环境升级导致头文件路径漂移。
- 在 CI 中加入“编译检查”任务,让
core_cm0plus.h缺失这类问题在合并代码前就被拦截。 - 日志中不要打印敏感的外设寄存器值或内存内容。GLM-5.3 审计时对“敏感信息泄露”的关注度很高,这类问题往往被忽略。
- 对于中断回调函数,建议人工重点复核,不建议完全交给大模型判断,因为实时性时序问题大模型无法感知。
7. 总结与下一步学习路线
在这一次开源项目审计实战中,我们用 GLM-5.3 完成了从“编译报错根因分析”到“核心代码安全缺陷挖掘”再到“审计报告输出”的全流程。围绕这个主题,我把项目实践中的经验教训整理成了上述章节,并重点分析了嵌入式场景下两个最常见也最“上头”的头文件缺失问题:arm_acle.h和core_cm0plus.h。说实话,这两个问题不难解决,但在大模型辅助下定位根因的速度确实提升明显——它省去了大量翻阅文档和搜索论坛的时间,直接把排查步骤按优先级排好。
从学习路线上看,如果你对“大模型辅助代码审计”这个话题感兴趣,下一步可以重点研究这三个方向:
- 如何把 GLM-5.3 接入 CI/CD 流水线,实现提交代码后自动生成的“代码审查意见”。
- 如何优化 Prompt,让模型输出更精准的漏洞定位,甚至少出现“幻觉”问题。
- 如何构建团队内部的审计知识库,把每一次审计发现沉淀下来,反过来继续指导大模型做更专业的判断。
在实际项目中,最需要优先关注的风险依然是“模型结论的可靠性”和“敏感数据的安全使用”这两条线。工具再强,也不能替代有经验工程师的最终判断。建议阅读完本文后,先拿自己手头的一个小模块试试,跑通“编译 - 筛查 - 深度审计 - 报告输出”这条链路。多跑几次,自然就形成了自己的审计方法论。