3. 审查对象与代码资产梳理
代码安全审查的第一步不是打开某个文件找漏洞,而是先回答一个更基础的问题:这个系统里到底有哪些东西需要审?如果审查对象没有盘清,后续的规则配置、工具选型和人力分配都会失焦——要么漏审关键资产,要么把大量时间花在低风险文件上。本节围绕六类典型审查对象展开:源代码、二进制、配置、依赖、IaC(基础设施即代码)和 CI/CD 脚本,并给出仓库结构分析、资产清单与优先级排序的可落地方法。
六类审查对象及其识别特征
源代码是最直观的对象,但识别时要注意区分业务代码、框架代码、自动生成代码和第三方内嵌代码。自动生成的代码(如 protobuf 生成文件、ORM 映射文件)通常不应作为人工审查重点,但需要在清单中标注来源,避免误判为“未覆盖”。
二进制包括编译产物、预编译库、容器镜像中的可执行文件。审查重点不是逐字节逆向,而是确认其来源可信、版本可追溯、是否包含已知漏洞组件。识别信号包括文件扩展名(.so、.dll、.exe、.jar)、构建产物目录(target/、dist/、build/)以及镜像层中的可执行文件。
配置涵盖应用配置、中间件配置、密钥与凭据文件。典型对象有 application.yml、nginx.conf、.env、settings.py 中的敏感项。配置审查的核心是“是否泄露、是否过宽、是否可被外部覆盖”。
依赖指直接与间接引入的第三方包。识别依据是包管理文件:pom.xml、package.json、requirements.txt、go.mod、Cargo.toml 等,以及对应的锁文件(package-lock.json、poetry.lock)。锁文件比声明文件更能反映真实运行时依赖。
IaC 包括 Terraform、CloudFormation、Kubernetes YAML、Ansible Playbook 等。它们描述的是基础设施与部署形态,一旦配置不当,风险等级往往高于单个应用漏洞,例如公开的 S3 桶、过宽的 IAM 策略、特权容器。
CI/CD 脚本包括 .github/workflows/、.gitlab-ci.yml、Jenkinsfile、构建脚本等。它们掌握着构建、测试、发布链路的权限,是供应链攻击的高价值目标,需要重点检查密钥引用方式、第三方 Action 版本固定情况、脚本注入风险。
代码仓库结构分析
拿到一个仓库后,先看顶层目录结构,再逐层下钻。常见的结构信号包括:src/ 或 app/ 通常是业务代码;config/、conf/、settings/ 是配置集中区;infra/、deploy/、k8s/ 是 IaC 所在;.github/workflows/、.gitlab-ci.yml、Jenkinsfile 是 CI/CD 脚本;vendor/、third_party/、node_modules/ 是第三方代码;dist/、build/、target/ 是构建产物。
分析时建议同时关注多模块仓库和单模块仓库的差异。多模块仓库(如 Maven 多模块、Gradle 多项目)需要先读根 pom.xml 或 settings.gradle,理清模块依赖关系,再决定审查顺序。单模块仓库则重点看入口文件和路由配置,快速定位对外暴露面。
一个容易被忽略的点是历史遗留目录。很多仓库里存在 legacy/、old/、backup/ 等目录,它们可能仍被部署脚本引用,也可能包含硬编码密钥。审查时不能因为名字带“old”就直接跳过,而应确认其是否仍在构建或部署链路中。
资产清单的字段设计
资产清单不是简单的文件列表,而是一张可追踪、可排序、可复核的工作表。建议至少包含以下字段:
| 字段 | 说明 | 示例 |
|---|---|---|
| 资产路径 | 仓库内相对路径 | src/main/java/com/acme/auth/LoginController.java |
| 资产类型 | 六类之一 | 源代码 |
| 责任人 | 模块负责人或团队 | 认证组 |
| 最近变更 | 最近一次提交时间 | 2025-03-12 |
| 暴露面 | 是否对外可访问 | 是(HTTP 接口) |
| 数据敏感度 | 是否处理敏感数据 | 高(凭据、令牌) |
| 审查状态 | 未审 / 审查中 / 已审 | 未审 |
| 风险等级 | P0~P3 | P0 |
清单的粒度需要权衡。按文件逐条登记会产生大量低价值条目,按目录登记又可能漏掉关键文件。折中做法是:P0/P1 资产按文件登记,P2/P3 资产按目录或模块登记。这样既保证关键资产可追踪,又控制清单规模。
审查优先级排序方法
优先级排序的核心是四个维度的乘积:暴露面 × 权限 × 数据敏感度 × 变更频率。暴露面指是否可被外部访问;权限指该资产在系统中的执行权限;数据敏感度指是否接触凭据、个人信息或核心业务数据;变更频率指近期提交活跃度——频繁变更的代码更容易引入新问题。
以某电商系统为例,排序结果可能是:CI/CD 脚本中的密钥引用(P0,因为掌握发布权限且可能泄露凭据)、公开的 IaC 模板(P0,可能直接暴露存储桶或数据库)、认证授权代码(P0,直接决定访问控制)、外部输入处理代码(P1,存在注入风险)、依赖中的高危组件(P1,已知漏洞可直接利用)、内部业务逻辑(P2)、自动生成代码(P3)。
实操示例:从仓库到清单
假设拿到一个 Spring Boot 项目,仓库根目录如下:
acme-order-service/
├── src/main/java/ # 业务源码
├── src/main/resources/
│ ├── application.yml # 应用配置
│ └── application-prod.yml
├── pom.xml # 依赖声明
├── infra/
│ ├── main.tf # Terraform
│ └── k8s/deployment.yaml
├── .github/workflows/
│ └── deploy.yml # CI/CD
├── .env # 本地环境变量
└── target/ # 构建产物
梳理步骤:先执行 find . -maxdepth 3 -type f | head -100 快速浏览文件分布;再用 grep -r "password\|secret\|token" --include="*.yml" --include="*.tf" --include="*.yml" . 定位潜在敏感配置;然后读取 pom.xml 确认依赖清单,读取 deploy.yml 确认发布流程中是否引用密钥;最后按上表字段逐条登记,并给出 P0~P3 排序。
完成后的清单应能回答三个问题:哪些资产必须人工审、哪些可以工具扫、哪些可以暂时不审。如果清单无法支撑这三个判断,说明字段设计或排序依据还需要调整。
资产梳理完成后,后续的规则配置、工具选型和审查排期才有依据。下一阶段的工作将围绕这些已识别的资产展开具体审查,而清单本身也会在审查过程中持续更新。