摘要

随着大模型能力的不断提升,AI 已经不再只是“帮我解释一段代码”或者“帮我写一个函数”的辅助工具,而是逐渐进入代码审计、安全评审、漏洞排查和研发质量治理等更复杂的工程场景。对于开发者和安全工程师来说,AI 代码审计并不是让模型“自动找漏洞”,而是把大模型作为一个高效的辅助分析器,用来提升阅读代码、梳理调用链、识别风险点、生成修复建议、补充测试用例和沉淀审计报告的效率。

本文将围绕“如何使用 AI 做代码审计”展开,系统介绍 AI 代码审计的适用场景、基本流程、提示词设计、常见漏洞审计方法、实战示例、审计报告写法、与传统 SAST 工具的结合方式,以及企业落地时需要关注的安全边界。文章不追求把 AI 神化,而是从真实工程实践出发,说明 AI 在代码审计中能做什么、不能做什么、应该怎么用、如何降低误报和漏报。适合开发人员、安全工程师、架构师、测试人员以及希望提升代码质量的技术负责人阅读。

关键词

AI代码审计大模型代码安全SAST漏洞分析提示词工程安全评审研发质量


一、为什么要用 AI 做代码审计?

代码审计一直是软件安全和软件质量保障中的重要环节。传统代码审计通常依赖三类方式:

第一类是人工审计。安全工程师或资深开发人员手动阅读代码,结合业务逻辑、框架特性和安全经验判断是否存在漏洞。这种方式准确率较高,但非常依赖经验,效率也比较低。面对大型项目时,人工审计往往很难覆盖全部代码。

第二类是静态分析工具,也就是常说的 SAST。比如 SonarQube、Checkmarx、Fortify、Semgrep、CodeQL 等工具都可以对代码进行规则化扫描,自动发现 SQL 注入、路径穿越、硬编码密钥、不安全函数调用等问题。这类工具适合规模化扫描,但问题也很明显:误报较多、上下文理解有限、对业务逻辑漏洞识别能力不足。

第三类是动态测试和渗透测试。通过运行系统、构造输入、观察响应来发现问题。这类方式更贴近真实攻击面,但通常需要环境、数据和交互流程配合,且不一定能定位到具体代码原因。

AI 代码审计的出现,并不是要替代上述方法,而是给代码审计增加一个新的辅助层。大模型擅长阅读自然语言和代码,能够快速理解上下文、解释调用关系、总结风险点、生成修复建议。这些能力正好可以弥补传统工具在“理解代码意图”和“解释问题原因”方面的不足。

举个简单例子,传统扫描工具可能告诉你:


存在潜在 SQL 注入风险:userId 参数拼接到了 SQL 字符串中。

但 AI 可以进一步帮你分析:


该方法从 HTTP 请求参数中读取 userId,未进行类型校验,随后直接拼接到 SQL 语句中。
如果攻击者传入异常字符串,可能改变 SQL 查询语义。
建议使用参数化查询,并在进入 service 层之前校验 userId 是否为数字类型。

也就是说,AI 的价值不只是“发现问题”,更在于“解释问题、串联上下文、生成修复方案、沉淀审计文档”。


二、AI 代码审计适合哪些场景?

AI 代码审计适合的场景非常多,但并不是所有场景都适合完全依赖 AI。下面按实际工作中的常见需求进行分类。

1. 新项目接手时的安全摸底

当我们接手一个陌生项目时,通常需要快速了解:

  • 项目使用什么技术栈;
  • 入口文件在哪里;
  • 权限认证怎么做;
  • 数据库访问层在哪里;
  • 外部接口调用在哪里;
  • 文件上传、下载、导入导出功能在哪里;
  • 是否存在定时任务、消息队列、异步任务等后台逻辑。

这些信息靠人工梳理需要较长时间,而 AI 可以快速阅读目录结构并生成项目安全画像。

示例提示词:


请以安全审计视角分析当前项目结构,重点关注:
1. 用户输入入口;
2. 身份认证和权限控制;
3. 数据库访问层;
4. 文件上传和文件下载;
5. 外部命令执行;
6. 第三方接口调用;
7. 可能涉及敏感信息的位置。

请先只读分析,不要修改任何代码。

2. 提交代码前的安全评审

在日常开发中,我们经常需要审查某次 Git diff 是否引入安全问题。AI 非常适合做这种“增量审计”。

示例提示词:


请审查当前 Git diff,重点关注是否引入以下问题:
1. 未授权访问;
2. 参数校验缺失;
3. SQL 注入;
4. 路径穿越;
5. 敏感信息泄露;
6. 日志打印敏感字段;
7. 异常处理不当。

请按“风险等级、问题位置、原因分析、修复建议”的格式输出。

这种用法非常适合和代码提交、Merge Request、Pull Request 流程结合。

3. 针对高危模块的专项审计

有些模块天然风险较高,例如:

  • 登录认证;
  • 权限校验;
  • 文件上传;
  • 文件下载;
  • 支付回调;
  • 订单状态流转;
  • 管理后台;
  • 数据导入导出;
  • WebHook;
  • OpenAPI;
  • RPC 接口;
  • 反序列化;
  • 模板渲染;
  • 命令执行;
  • SSRF 相关请求转发。

这类模块即使用了扫描工具,也需要人工深入看业务逻辑。AI 可以帮助我们梳理调用链、识别输入输出边界、列出攻击面和修复建议。

4. 老旧系统安全治理

很多企业系统历史较长,代码风格不统一,缺少文档,开发人员也可能已经变动。安全治理时,最困难的是“没人说得清这个系统怎么跑”。

AI 在这里可以发挥很大作用:

  • 自动生成模块说明;
  • 梳理接口和数据库表关系;
  • 识别重复代码和危险函数;
  • 汇总硬编码配置;
  • 帮助生成整改计划;
  • 输出审计报告初稿。

5. 安全知识不足的开发团队

很多业务开发并不是安全专家。让每个开发者都熟练掌握所有漏洞原理并不现实,但可以把 AI 当作安全助手,让它在代码提交前做一轮辅助检查。

例如开发者可以在提交前输入:


请从安全角度检查我刚刚修改的代码,告诉我是否有明显风险。
如果有风险,请用开发者能理解的方式解释原因,并给出最小改动修复方案。

这并不能替代专业安全团队,但可以显著降低低级安全问题进入主干分支的概率。


三、AI 代码审计不能做什么?

在强调 AI 能力之前,必须先讲清楚边界。

AI 不是万能审计工具,也不是自动漏洞挖掘神器。它在代码审计中存在以下局限。

1. AI 可能误报

AI 有时会把理论上存在的问题判断成真实漏洞。例如看到字符串拼接就认为一定存在 SQL 注入,但实际上参数可能在上游已经做了严格白名单校验。

因此,AI 给出的结论必须经过人工确认。

2. AI 可能漏报

AI 的上下文有限,尤其是在没有完整项目、没有运行环境、没有数据库结构、没有配置文件的情况下,可能看不到关键风险点。

例如权限校验可能在 AOP、Filter、Interceptor、网关或配置文件中完成。如果模型只看 Controller,就可能误判。

3. AI 不理解全部业务语义

很多业务逻辑漏洞并不是代码语法问题,而是业务规则问题。例如:

  • 优惠券重复领取;
  • 订单越权查看;
  • 审批流程绕过;
  • 退款金额大于支付金额;
  • 用户可以修改不属于自己的资源;
  • 状态机流转缺少约束。

这些问题需要业务背景。AI 可以帮助分析,但前提是我们要提供足够的业务规则说明。

4. AI 不应该直接操作生产代码

如果使用 Agent 类工具做代码审计,一定要避免让 AI 在未确认的情况下直接修改重要代码。尤其不能在生产环境、生产服务器、敏感仓库中使用自动执行模式。

正确方式是:

  1. 先只读分析;
  2. 输出审计结论;
  3. 人工确认问题;
  4. 再让 AI 给修复建议;
  5. 最后由开发者审查 diff 并提交。

四、AI 代码审计的标准流程

一个比较稳妥的 AI 代码审计流程可以分为七步。

第一步:明确审计目标

不要一上来就说:


帮我审计这个项目。

这个提示太宽泛,AI 很容易泛泛而谈。

更好的方式是明确范围:


请审计用户登录和权限校验相关代码,重点关注:
1. 是否存在认证绕过;
2. 是否存在越权访问;
3. Token 校验是否完整;
4. 登录失败处理是否安全;
5. 是否存在敏感信息泄露。

请先输出审计思路,再开始分析。

审计目标越明确,结果越可用。

第二步:让 AI 先梳理结构

在分析漏洞前,先让 AI 理解项目。


请先阅读项目结构,找出与认证、权限、用户管理相关的文件。
暂时不要判断漏洞,只输出相关文件列表和作用说明。

这样可以避免模型过早下结论。

第三步:识别输入入口

代码审计的核心是数据流。用户输入从哪里进入系统?经过哪些处理?最后流向哪里?

常见输入入口包括:

  • HTTP 请求参数;
  • Header;
  • Cookie;
  • JSON Body;
  • 文件上传内容;
  • URL path variable;
  • 消息队列消息;
  • 定时任务读取的数据;
  • 第三方回调参数;
  • RPC 入参;
  • 命令行参数;
  • 配置文件;
  • 环境变量。

提示词:


请找出当前模块所有外部输入入口,并整理为表格:
字段包括:入口位置、参数名称、来源、后续调用链、最终流向、是否有校验。

第四步:跟踪危险流向

危险流向通常包括:

  • SQL 查询;
  • 文件路径;
  • 系统命令;
  • 模板渲染;
  • 反序列化;
  • HTTP 请求转发;
  • 日志输出;
  • 响应输出;
  • 权限判断;
  • 加密解密;
  • 反射调用。

提示词:


请跟踪这些用户输入最终流向哪些敏感操作,例如 SQL、文件系统、命令执行、HTTP 请求、模板渲染和日志输出。
如果发现风险,请说明完整数据流。

第五步:判断是否有防护

不能只看危险函数,还要看是否存在防护措施。例如:

  • 是否有参数化查询;
  • 是否有白名单;
  • 是否有鉴权;
  • 是否有权限校验;
  • 是否有路径规范化;
  • 是否限制文件类型;
  • 是否限制文件大小;
  • 是否过滤敏感日志;
  • 是否有 CSRF 防护;
  • 是否有重放保护;
  • 是否校验签名。

提示词:


请不要只根据危险函数下结论。
请同时检查是否存在有效防护,例如白名单、参数化查询、权限校验、路径规范化和签名校验。
最后再判断风险是否成立。

第六步:输出审计结论

建议要求 AI 按固定格式输出,方便后续整理报告。


请按以下格式输出审计结果:

## 问题 1:标题
- 风险等级:
- 影响位置:
- 问题描述:
- 触发条件:
- 数据流:
- 影响范围:
- 修复建议:
- 是否需要人工确认:

第七步:生成修复建议和测试用例

审计不是为了“指出问题”,而是为了“解决问题”。好的审计流程应该包含修复方案和验证方式。


请针对上述问题给出最小改动修复方案,并补充对应的单元测试思路。
注意不要改变现有接口行为。

五、常见漏洞类型的 AI 审计方法

下面从常见风险类型出发,说明如何使用 AI 辅助审计。


1. SQL 注入审计

SQL 注入是最常见的输入流向数据库风险。AI 审计时需要关注:

  • 是否存在字符串拼接 SQL;
  • 是否使用参数化查询;
  • ORM 是否正确绑定参数;
  • 排序字段、表名、列名是否可控;
  • MyBatis ${}#{} 是否混用不当;
  • 是否存在动态 SQL 拼接;
  • 是否有白名单校验。

示例提示词:


请审计当前项目中的数据库查询代码,重点关注 SQL 注入风险。
请特别检查:
1. 字符串拼接 SQL;
2. MyBatis XML 中的 ${};
3. 动态 order by;
4. 动态表名或字段名;
5. 原生 SQL 查询;
6. 参数是否经过白名单校验。

容易被忽略的是 order by 场景。例如:


String sql = "select * from user order by " + sortField;

即使 sortField 不是普通查询条件,也可能改变 SQL 语义。修复方式通常是白名单映射:


private static final Map<String, String> SORT_FIELD_MAP = Map.of(
    "name", "name",
    "createdTime", "created_time",
    "id", "id"
);

String column = SORT_FIELD_MAP.get(sortField);
if (column == null) {
    throw new IllegalArgumentException("Invalid sort field");
}

String sql = "select * from user order by " + column;

这里不能简单使用参数占位符替代表名或列名,因为数据库参数化通常只适用于值,不适用于 SQL 结构。因此 AI 审计时必须让它区分“值参数”和“结构参数”。


2. 越权访问审计

越权是业务系统中最常见、也最容易漏掉的问题。它不是语法漏洞,而是权限逻辑漏洞。

常见越权类型包括:

  • 用户 A 查看用户 B 的订单;
  • 普通用户访问管理员接口;
  • 子账号操作主账号资源;
  • 租户 A 访问租户 B 数据;
  • 只校验登录,不校验资源归属;
  • 前端隐藏按钮,但后端没有校验;
  • 接口只根据传入 userId 查询数据。

提示词:


请审计当前接口是否存在越权访问风险。
重点关注:
1. Controller 是否从请求参数中直接接收 userId、tenantId、orgId;
2. Service 层是否校验资源归属;
3. 是否只判断登录状态,没有判断操作权限;
4. 管理员接口是否有角色校验;
5. 多租户数据查询是否强制带租户条件。

典型风险代码:


@GetMapping("/order/detail")
public Order getOrder(@RequestParam Long orderId) {
    return orderService.getById(orderId);
}

如果这里没有判断订单是否属于当前用户,就可能存在越权。

修复示例:


@GetMapping("/order/detail")
public Order getOrder(@RequestParam Long orderId) {
    Long currentUserId = SecurityContext.getCurrentUserId();
    return orderService.getByIdAndUserId(orderId, currentUserId);
}

AI 审计时要注意,权限校验可能不在当前方法里,而在注解、拦截器、AOP 或网关中。因此提示词中要明确要求它查找全局鉴权机制。


3. 文件上传审计

文件上传是高危功能。AI 审计时应关注:

  • 是否限制文件大小;
  • 是否校验扩展名;
  • 是否校验 MIME Type;
  • 是否校验真实文件内容;
  • 是否使用随机文件名;
  • 是否允许覆盖已有文件;
  • 是否上传到 Web 可执行目录;
  • 是否支持压缩包上传;
  • 是否存在 Zip Slip;
  • 是否对图片进行安全处理;
  • 是否存储原始文件名;
  • 是否记录上传者和访问权限。

提示词:


请审计文件上传功能,重点关注:
1. 文件类型校验是否可靠;
2. 文件名是否可控;
3. 保存路径是否可控;
4. 是否限制文件大小;
5. 是否可能上传可执行脚本;
6. 是否可能覆盖已有文件;
7. 是否存在压缩包路径穿越风险。

典型风险代码:


String fileName = file.getOriginalFilename();
file.transferTo(new File(uploadDir + "/" + fileName));

风险点包括:

  • fileName 可能包含路径;
  • 可能覆盖已有文件;
  • 文件扩展名可伪造;
  • 可能上传到可访问目录。

更安全的处理方式:


String originalName = file.getOriginalFilename();
String ext = getSafeExtension(originalName);

if (!ALLOWED_EXTENSIONS.contains(ext)) {
    throw new IllegalArgumentException("Unsupported file type");
}

String safeName = UUID.randomUUID().toString() + "." + ext;
Path target = Paths.get(uploadDir).resolve(safeName).normalize();

if (!target.startsWith(Paths.get(uploadDir))) {
    throw new SecurityException("Invalid upload path");
}

file.transferTo(target.toFile());

AI 可以帮助识别这类问题,但最终仍需要结合实际部署方式判断风险。例如文件上传到对象存储和上传到 Web 根目录,风险是不一样的。


4. 文件下载与路径穿越审计

文件下载经常出现路径穿越问题。典型风险是用户可以通过参数控制文件路径。

风险代码:


@GetMapping("/download")
public void download(String fileName, HttpServletResponse response) throws IOException {
    File file = new File(baseDir + "/" + fileName);
    Files.copy(file.toPath(), response.getOutputStream());
}

如果用户传入特殊路径,可能读取非预期文件。

提示词:


请审计文件下载接口是否存在路径穿越风险。
重点关注:
1. 用户是否可以控制文件名或路径;
2. 是否进行了路径 normalize;
3. 是否校验最终路径必须位于 baseDir 内;
4. 是否允许下载任意后缀;
5. 是否有权限校验。

安全写法:


Path basePath = Paths.get(baseDir).toAbsolutePath().normalize();
Path targetPath = basePath.resolve(fileName).normalize();

if (!targetPath.startsWith(basePath)) {
    throw new SecurityException("Invalid file path");
}

这里的关键点是:不能只过滤字符串中的 ../,而应该进行路径规范化后判断最终路径是否仍在允许目录下。


5. 命令执行审计

命令执行风险通常出现在系统运维、文件转换、视频处理、压缩解压、脚本调用等场景。

风险代码:


Runtime.getRuntime().exec("ping " + host);

如果 host 来自用户输入,就可能导致命令参数被污染。

提示词:


请审计项目中所有系统命令执行点,重点关注:
1. Runtime.exec;
2. ProcessBuilder;
3. shell 脚本调用;
4. Python subprocess;
5. Node.js child_process;
6. 用户输入是否进入命令参数;
7. 是否使用白名单限制。

建议修复方式:

  • 避免调用 shell;
  • 使用参数数组;
  • 对参数做白名单;
  • 限制命令范围;
  • 不允许用户控制完整命令;
  • 使用专门库替代系统命令。

例如:


ProcessBuilder pb = new ProcessBuilder("ping", "-c", "4", host);

同时还要校验 host:


if (!host.matches("^[a-zA-Z0-9.-]+$")) {
    throw new IllegalArgumentException("Invalid host");
}

AI 在审计命令执行时很有帮助,因为它可以全局搜索危险 API,并分析参数来源。


6. SSRF 审计

SSRF 通常发生在服务端根据用户输入发起 HTTP 请求的场景,例如:

  • 图片抓取;
  • URL 预览;
  • WebHook;
  • 文件导入;
  • 代理转发;
  • 第三方接口回调测试;
  • PDF 转换;
  • 远程资源下载。

提示词:


请审计项目中所有服务端 HTTP 请求发起点,重点关注 SSRF 风险。
请检查:
1. URL 是否来自用户输入;
2. 是否限制协议为 http/https;
3. 是否禁止访问内网地址;
4. 是否处理重定向;
5. 是否校验 DNS 解析结果;
6. 是否存在代理转发接口;
7. 是否限制响应大小和超时时间。

常见风险代码:


String url = request.getParameter("url");
String result = restTemplate.getForObject(url, String.class);

安全修复思路包括:

  • 只允许访问白名单域名;
  • 禁止访问内网 IP;
  • 禁止 file、gopher 等非预期协议;
  • 限制重定向;
  • DNS 解析后检查 IP;
  • 设置超时;
  • 限制响应大小;
  • 不返回完整错误信息。

这里要注意,SSRF 的安全校验比较复杂,AI 给出的修复代码需要人工仔细审查。


7. 敏感信息泄露审计

敏感信息泄露包括:

  • 代码中硬编码密码;
  • 日志打印 token;
  • 返回接口包含手机号、身份证、银行卡;
  • 异常堆栈直接返回前端;
  • 配置文件泄露密钥;
  • Git 历史中存在 secret;
  • 测试数据包含真实用户信息。

提示词:


请审计项目中可能存在的敏感信息泄露问题。
重点关注:
1. 配置文件中的密钥;
2. 日志中打印密码、token、cookie、身份证、手机号;
3. 接口响应是否返回过多用户信息;
4. 异常信息是否直接暴露;
5. 测试文件中是否包含真实凭据。

常见风险代码:


log.info("login request: {}", loginRequest);

如果 loginRequest 中包含密码,就可能泄露。

更好的方式:


log.info("login request username={}", loginRequest.getUsername());

或者对敏感字段脱敏:


log.info("user phone={}", maskPhone(phone));

AI 很适合做这类审计,因为它可以帮助我们从大量代码中找出日志打印和配置项。


8. 反序列化审计

反序列化风险在 Java、PHP、Python、Node.js 等语言中都可能出现。审计时要关注:

  • 是否反序列化不可信输入;
  • 是否使用危险库;
  • 是否允许动态类型;
  • 是否存在 gadget 链依赖;
  • 是否有签名校验;
  • 是否限制类型白名单。

提示词:


请审计项目中所有反序列化相关代码,重点关注:
1. Java ObjectInputStream;
2. Fastjson、Jackson 多态类型;
3. Python pickle;
4. PHP unserialize;
5. Node.js serialize/deserialize;
6. 反序列化数据是否来自用户输入;
7. 是否有类型白名单和签名校验。

这类问题往往和依赖版本、配置方式强相关。AI 可以帮助定位风险点,但最终判断要结合依赖版本和运行配置。


六、AI 代码审计提示词模板

下面给出一些可以直接复制使用的提示词模板。

1. 项目安全画像模板


你现在是一名代码安全审计工程师。
请以只读方式分析当前项目,输出项目安全画像。

要求:
1. 判断项目技术栈;
2. 找出主要入口文件;
3. 梳理认证和权限控制机制;
4. 找出数据库访问层;
5. 找出文件上传、下载、导入导出功能;
6. 找出外部 HTTP 请求调用点;
7. 找出系统命令执行点;
8. 找出配置文件和敏感信息位置;
9. 不要修改任何文件;
10. 输出后给出下一步审计建议。

2. Git Diff 审计模板


请审计当前 Git diff,判断本次改动是否引入安全风险。

重点关注:
1. 权限校验是否缺失;
2. 用户输入是否进入 SQL、文件路径、命令、HTTP 请求;
3. 是否新增敏感日志;
4. 是否新增硬编码密钥;
5. 是否新增不安全依赖;
6. 是否改变认证逻辑;
7. 是否改变数据权限范围。

输出格式:
- 风险等级
- 文件位置
- 问题描述
- 成立条件
- 修复建议
- 是否需要人工确认

3. 接口越权审计模板


请审计当前模块的接口越权风险。
请逐个接口分析:
1. 接口路径;
2. 是否需要登录;
3. 是否需要角色权限;
4. 是否校验资源归属;
5. 是否直接使用用户传入的 userId、tenantId、orgId;
6. 是否存在水平越权;
7. 是否存在垂直越权;
8. 修复建议。

请不要只看 Controller,也要检查 Service、DAO、注解、拦截器和 AOP。

4. 数据流审计模板


请对以下参数进行数据流分析:
参数名称:xxx
入口位置:xxx

请分析:
1. 参数从哪里进入;
2. 经过哪些函数;
3. 是否经过校验;
4. 最终流向哪里;
5. 是否进入敏感操作;
6. 风险是否成立;
7. 如果成立,如何修复。

5. 审计报告生成模板


请根据以上审计结果生成一份正式代码审计报告。

报告结构:
1. 审计背景;
2. 审计范围;
3. 审计方法;
4. 风险总览;
5. 问题详情;
6. 修复建议;
7. 复测建议;
8. 总结。

要求语言正式、客观,适合提交给研发团队和项目负责人。

七、AI 与传统安全工具如何结合?

AI 代码审计不是替代 SAST,而是和 SAST 形成互补。

一个推荐流程是:

1. 先用 SAST 做全量扫描

使用 SonarQube、Semgrep、CodeQL 等工具先做全量扫描,得到初步风险列表。

2. 再让 AI 分析扫描结果

把扫描结果交给 AI,让它帮助分类:


请分析这份 SAST 扫描结果,帮我完成:
1. 去除明显误报;
2. 按风险等级排序;
3. 合并重复问题;
4. 判断哪些问题需要优先修复;
5. 为每类问题给出修复建议。

3. 对高危问题做人工确认

高危问题必须人工确认,尤其是:

  • 认证绕过;
  • 越权;
  • SQL 注入;
  • 任意文件读取;
  • 命令执行;
  • SSRF;
  • 敏感信息泄露;
  • 供应链风险。

4. 让 AI 生成修复代码

确认问题成立后,可以让 AI 生成最小改动方案。


这个问题确认成立。
请给出最小改动修复方案,要求:
1. 不改变接口协议;
2. 不影响现有业务逻辑;
3. 补充单元测试;
4. 说明修复前后的行为差异。

5. 再用测试和扫描工具复测

修复后不能只相信 AI,需要重新运行:

  • 单元测试;
  • 集成测试;
  • SAST 扫描;
  • 关键接口手工验证;
  • 安全回归测试。

八、AI 代码审计实战示例

假设有如下 Java Controller:


@RestController
@RequestMapping("/api/report")
public class ReportController {

    @GetMapping("/download")
    public void download(@RequestParam String fileName,
                         HttpServletResponse response) throws IOException {
        String baseDir = "/data/reports/";
        File file = new File(baseDir + fileName);

        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        Files.copy(file.toPath(), response.getOutputStream());
    }
}

我们可以给 AI 的提示词是:


请审计这段文件下载代码,判断是否存在安全风险。
请从用户输入、文件路径、权限校验、响应头、安全修复几个角度分析。

AI 应该能识别出以下问题:

  1. fileName 来自用户输入;
  2. 直接拼接到文件路径;
  3. 没有路径规范化;
  4. 没有判断最终文件是否位于 /data/reports/ 下;
  5. 没有权限校验;
  6. 响应头中直接使用原始文件名,可能存在响应头注入风险;
  7. 未处理文件不存在和异常情况。

更安全的修复示例:


@RestController
@RequestMapping("/api/report")
public class ReportController {

    private static final Path BASE_DIR = Paths.get("/data/reports/").toAbsolutePath().normalize();

    @GetMapping("/download")
    public void download(@RequestParam String fileName,
                         HttpServletResponse response) throws IOException {

        if (fileName == null || fileName.contains("\r") || fileName.contains("\n")) {
            throw new IllegalArgumentException("Invalid file name");
        }

        Path targetPath = BASE_DIR.resolve(fileName).normalize();

        if (!targetPath.startsWith(BASE_DIR)) {
            throw new SecurityException("Invalid file path");
        }

        if (!Files.exists(targetPath) || !Files.isRegularFile(targetPath)) {
            throw new FileNotFoundException("File not found");
        }

        String safeDownloadName = targetPath.getFileName().toString();

        response.setHeader(
            "Content-Disposition",
            "attachment; filename=\"" + safeDownloadName.replace("\"", "") + "\""
        );

        Files.copy(targetPath, response.getOutputStream());
    }
}

不过这还不是最终答案。实际项目中还应该继续确认:

  • 当前用户是否有权限下载该报表;
  • 报表文件是否与用户、部门、租户绑定;
  • 是否应该通过文件 ID 查询数据库,而不是直接传文件名;
  • 是否需要审计日志;
  • 是否限制下载频率;
  • 是否需要对敏感报表加水印或脱敏。

这就是 AI 代码审计的重要原则:AI 可以快速发现技术风险,但业务安全需要结合真实业务规则判断。


九、如何降低 AI 审计误报?

AI 审计误报不可避免,但可以通过方法降低。

1. 提供完整上下文

不要只给一个函数,尽量提供:

  • Controller;
  • Service;
  • DAO;
  • 配置;
  • 权限注解;
  • 拦截器;
  • 数据库表结构;
  • 业务规则。

上下文越完整,AI 判断越准确。

2. 要求 AI 说明“成立条件”

不要让 AI 只输出“存在漏洞”,而要让它说明漏洞成立需要哪些条件。


请不要直接下结论。
对于每个风险,请说明:
1. 风险成立需要哪些前提条件;
2. 当前代码中哪些证据支持该判断;
3. 还缺少哪些信息需要人工确认。

3. 要求区分“疑似风险”和“确认风险”


请将问题分为两类:
1. 已确认风险:根据当前代码可以确认成立;
2. 疑似风险:需要更多上下文或运行环境确认。

4. 让 AI 做反向验证


请尝试反驳你刚才的漏洞判断。
如果代码中存在防护措施,请指出。
如果证据不足,请降低风险等级。

这个方法非常实用,可以减少 AI 过度自信。


十、如何降低 AI 审计漏报?

1. 分模块审计

不要一次性让 AI 审计整个大型项目。可以按模块拆分:

  • 登录模块;
  • 用户模块;
  • 权限模块;
  • 文件模块;
  • 支付模块;
  • 管理后台;
  • 数据导入导出模块。

2. 按漏洞类型审计

同一个模块可以多轮审计:

第一轮看越权;

第二轮看 SQL 注入;

第三轮看文件风险;

第四轮看日志和敏感信息;

第五轮看异常处理。

3. 结合搜索关键词

可以让 AI 搜索危险函数和关键字:


请在项目中搜索以下关键词,并分析是否存在安全风险:
Runtime.exec
ProcessBuilder
ObjectInputStream
@RequestParam
MultipartFile
RestTemplate
WebClient
FileInputStream
FileOutputStream
createNativeQuery
${}

4. 使用清单化方法

代码审计最好有 checklist。AI 很适合按照清单逐项检查。

示例:


请按照以下 checklist 审计当前模块:
1. 是否有身份认证;
2. 是否有权限校验;
3. 是否校验资源归属;
4. 是否校验输入参数;
5. 是否存在危险函数;
6. 是否打印敏感日志;
7. 是否正确处理异常;
8. 是否有单元测试覆盖;
9. 是否有审计日志;
10. 是否符合最小权限原则。

十一、企业落地 AI 代码审计的建议

如果是在企业内部推广 AI 代码审计,不能只靠个人习惯,而应该形成流程。

1. 建立统一提示词模板

安全团队可以沉淀一套标准模板,例如:

  • Java Web 审计模板;
  • Spring Boot 权限审计模板;
  • MyBatis SQL 审计模板;
  • 文件上传审计模板;
  • 前端安全审计模板;
  • Python Flask 审计模板;
  • Node.js Express 审计模板;
  • Go Gin 审计模板。

这样开发人员不用自己写提示词,只需要套用模板即可。

2. 建立安全规则库

把企业内部常见问题整理成规则:

  • Controller 不允许直接信任 userId;
  • 所有下载必须基于文件 ID;
  • 管理接口必须带角色注解;
  • 日志不允许打印 token;
  • SQL 排序字段必须白名单;
  • 文件上传必须走统一组件;
  • 外部 URL 请求必须经过 SSRF 防护组件。

然后让 AI 按规则库审计。

3. 接入代码评审流程

可以在 Pull Request 中增加 AI 审计环节:

  1. 开发提交代码;
  2. CI 运行测试和 SAST;
  3. AI 分析 diff 和扫描结果;
  4. 输出安全审查评论;
  5. 安全人员或负责人确认;
  6. 合并代码。

4. 保留人工最终决策

AI 可以提出建议,但不应该拥有最终合并权限。尤其是安全问题的风险等级、修复优先级和是否上线,必须由人来判断。

5. 注意代码和数据安全

企业使用 AI 审计时必须关注:

  • 是否允许代码上传到外部模型;
  • 是否包含商业机密;
  • 是否包含客户数据;
  • 是否包含密钥;
  • 是否需要私有化部署;
  • 是否需要脱敏;
  • 是否符合合规要求。

如果项目敏感,应优先考虑内网模型、私有化模型或本地审计工具。


十二、AI 代码审计报告怎么写?

一份好的代码审计报告不应该只是漏洞列表,而应该让研发团队知道问题在哪里、为什么危险、怎么修、如何验证。

推荐结构如下。

1. 审计背景

说明为什么做本次审计,例如:


本次审计针对 XX 系统近期版本变更进行安全评估,重点关注用户权限、文件处理、数据库访问和敏感信息保护等方面,目的是在上线前识别潜在安全风险。

2. 审计范围

列出审计模块:


审计范围包括:
1. 用户登录模块;
2. 订单查询模块;
3. 报表下载模块;
4. 管理后台接口;
5. 文件上传功能。

3. 审计方法

说明使用了哪些方式:


本次审计采用人工代码阅读、AI 辅助分析、静态扫描结果复核、关键调用链追踪等方式,对高风险接口进行重点检查。

4. 风险总览

可以用表格:


| 序号 | 风险名称 | 等级 | 影响模块 | 状态 |
|---|---|---|---|---|
| 1 | 报表下载存在路径穿越风险 | 高 | 报表模块 | 待修复 |
| 2 | 订单详情接口缺少资源归属校验 | 高 | 订单模块 | 待确认 |
| 3 | 登录日志打印敏感参数 | 中 | 登录模块 | 待修复 |

5. 问题详情

每个问题按固定格式写:


## 问题 1:报表下载存在路径穿越风险

- 风险等级:高
- 影响位置:ReportController.download
- 问题描述:接口直接使用用户传入的 fileName 拼接本地文件路径,未进行路径规范化和目录边界校验。
- 风险影响:攻击者可能尝试读取非预期目录下的文件。
- 修复建议:
  1. 使用 Path.resolve 和 normalize;
  2. 判断最终路径必须位于报表目录下;
  3. 使用文件 ID 查询数据库,不直接暴露文件名;
  4. 增加用户权限校验。
- 复测建议:构造异常文件名,验证接口是否拒绝访问。

6. 总结

总结整体风险:


本次审计发现系统整体权限控制框架较完整,但在部分业务接口中仍存在资源归属校验不足的问题。建议后续统一封装权限校验组件,并将文件上传下载、外部 URL 请求等高风险能力收敛到公共安全组件中。

十三、AI 代码审计的最佳实践

结合实际使用经验,建议遵守以下原则。

1. 不要让 AI 直接得结论

先让它梳理结构,再找入口,再分析数据流,最后判断风险。

2. 不要一次审计太大范围

大型项目要拆模块、拆漏洞类型、拆调用链。

3. 不要只问“有没有漏洞”

要问:

  • 输入从哪里来;
  • 有没有校验;
  • 流向哪里;
  • 防护是否有效;
  • 风险成立条件是什么;
  • 缺少哪些证据;
  • 如何修复;
  • 如何复测。

4. 不要忽视业务逻辑

AI 不知道你的真实业务规则。越权、支付、审批、订单、优惠券、退款等场景必须补充业务背景。

5. 不要跳过复测

修复建议必须经过测试验证。AI 说修好了,不等于真的修好了。

6. 不要上传敏感代码

涉及商业机密、客户数据、密钥、生产配置的代码,应先脱敏或使用企业认可的安全环境。


十四、一个完整的 AI 审计工作流示例

下面给出一个可以直接应用到项目中的完整工作流。

第一步:新建审计分支


git checkout -b security-audit-ai

第二步:查看项目状态


git status

第三步:让 AI 生成项目安全画像


请只读分析当前项目,生成项目安全画像,重点找出认证、权限、数据库、文件处理、外部请求和敏感配置相关模块。

第四步:选择高风险模块

例如 AI 发现存在文件下载模块,就继续:


请专项审计文件下载模块,重点关注路径穿越、越权下载、响应头注入和敏感文件泄露。

第五步:让 AI 输出风险列表


请将发现的问题按风险等级排序,并区分“确认风险”和“疑似风险”。

第六步:人工确认高危问题

开发者或安全人员阅读代码,确认 AI 判断是否成立。

第七步:生成修复方案


问题 1 已确认成立,请给出最小改动修复方案,并说明是否需要补充单元测试。

第八步:审查修改


git diff

第九步:运行测试


mvn test

或者:


npm test

第十步:生成审计报告


请根据本次审计过程生成一份正式审计报告,适合提交给项目组。

十五、总结

AI 代码审计不是让大模型“自动替我们找漏洞”,而是把大模型引入代码安全流程,让它承担重复性、结构化、辅助性的分析工作。它可以帮助我们快速理解项目、梳理调用链、识别危险函数、分析数据流、生成修复建议、补充测试思路和整理审计报告。

但 AI 不是安全专家的替代品。它可能误报,也可能漏报;它可以理解代码片段,但不一定理解完整业务;它可以给出修复建议,但不能替代人工评审和测试验证。因此,正确的使用方式应该是:

  1. 用 AI 提升审计效率;
  2. 用人工判断风险是否成立;
  3. 用测试验证修复是否有效;
  4. 用流程保证结果可追踪;
  5. 用安全边界保护代码和数据。

未来,AI 代码审计很可能会成为研发流程中的标准环节。它不会取代开发者和安全工程师,而是让安全能力更早进入开发阶段,让更多问题在提交前、合并前、上线前被发现和修复。

对于个人开发者来说,可以从 Git diff 审计、模块安全检查、日志敏感信息检查这些低成本场景开始。对于团队来说,可以逐步沉淀提示词模板、安全规则库、审计报告模板,并把 AI 审计接入 CI/CD 和代码评审流程中。

一句话总结:AI 代码审计的核心不是“让 AI 代替人做安全”,而是“让 AI 帮人更快、更系统、更有依据地做安全”。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐