关于 ci-sentinel
面向七种 CI 系统工作流文件的安全分析器,并提供已遭入侵组件的托管威胁情报源。它可通过 MCP 服务或 HTTP API 使用,并能输出问题、修复建议、合规等级和 SARIF 结果。
主要功能
- 01分析七种 CI 系统的工作流
- 02追踪注入与供应链风险
- 03通过实时威胁源检查组件
- 04生成修复内容和统一差异
- 05生成等级评估与 SARIF 报告
适用场景
- 01在拉取请求运行代码前审计 CI 工作流
- 02查找遭入侵或可变更的 CI 组件
- 03为代码扫描整理安全问题
MCP 相关
MCP 服务提供 `audit_ci_security` 工具,可接收工作流文件集合或单个源文件。免费层返回判定结果和各类问题数量;深度审计提供详细发现与修复建议。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://ci-sentinel.vercel.app/mcpclaude mcp add --transport http ci-sentinel https://ci-sentinel.vercel.app/mcp{"mcpServers":{"ci-sentinel":{"type":"http","url":"https://ci-sentinel.vercel.app/mcp"}}}在 Cursor 中打开{"servers":{"ci-sentinel":{"type":"http","url":"https://ci-sentinel.vercel.app/mcp"}}}在 VS Code 中打开{"mcpServers":{"ci-sentinel":{"type":"http","url":"https://ci-sentinel.vercel.app/mcp"}}}{"mcpServers":{"ci-sentinel":{"serverUrl":"https://ci-sentinel.vercel.app/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
ci-sentinel 🛡️
面向七种 CI 生态的安全审计工具——GitHub Actions、GitLab CI/CD、 Jenkins、CircleCI、Azure Pipelines、Bitbucket Pipelines 和 Travis CI——可发现 YAML 检查器无法识别的供应链漏洞和注入缺陷,避免攻击者的拉取请求/合并请求在运行代码时访问仓库机密。
可作为 MCP 服务(供 Claude / Cursor / 任意 Agent 使用),也可作为 按次付费的 HTTP API(支持 x402 USDC 或预付费卡密)。
提供 .github/workflows/*.yml、.gitlab-ci.yml、Jenkinsfile、
.circleci/config.yml、azure-pipelines.yml、bitbucket-pipelines.yml 和/或
.travis.yml(每个文件都会自动路由到相应的分析器),即可获得
CRITICAL / VULNERABLE / RISKY / HARDENED 判定和具体缺陷。
它能发现检查器无法发现的问题
| 类别 | ci-sentinel 的功能 |
|---|---|
| 💉 表达式注入(跨步骤/跨作业污点追踪) | 将不可信的 ${{ github.event.* }}(议题/PR 标题、正文、评论、审查、分支名称、提交消息、标签名称、派生仓库身份、编辑前的值)标记为污点,并追踪到 run: shell 或 actions/github-script 接收点——还会沿着 steps.<id>.outputs.*、needs.<job>.outputs.*、env: 变量、matrix 值和可复用工作流的 inputs.* 追踪。即使攻击者把不可信值藏在中间输出中,也能被发现;逐文件 grep 做不到这一点。 |
| 🎭 利用拉取请求 | 在具有特权且包含机密的上下文中,通过 pull_request_target / workflow_run 检出不可信的派生仓库代码,会导致攻击者利用机密执行任意代码。 |
| 🔑 令牌权限 | 权限过大的 GITHUB_TOKEN 范围(write-all、contents:write、id-token:write)、缺少 permissions: 块,以及机密暴露给不可信触发事件。 |
| 🔁 可复用工作流 | workflow_call 调用方通过 inputs.* 将不可信数据传过边界,以及在不可信触发事件中通过 secrets: inherit 将全部机密交给可复用工作流。 |
| 📌 固定 Action 版本 | 第三方 Action(以及可复用工作流的 uses:)使用可变标签/分支而非提交 SHA(如 tj-actions/changed-files 式劫持),并会追踪传递依赖 Action 图。 |
| 🖥️ 自托管运行器上的 RCE | 可从公开仓库 PR 访问的自托管运行器(攻击者可在你的基础设施上执行 RCE),以及滥用 OIDC id-token 信任。 |
……并以同样的深度分析 GitLab CI/CD(.gitlab-ci.yml)
| 类别 | ci-sentinel 的功能 |
|---|---|
| 💉 CI 变量注入 | 将插入 script: 的不可信 GitLab 变量(CI_COMMIT_REF_NAME/BRANCH/TAG、CI_MERGE_REQUEST_TITLE/DESCRIPTION/SOURCE_BRANCH_NAME、提交消息/作者、触发用户字段)标记为污点——沿着 variables: 和 extends: 模板追踪污点。能够识别安全变量(CI_COMMIT_SHA、CI_MERGE_REQUEST_IID、CI_PROJECT_ID 等),因此不会把每个 $CI_ 变量都标记出来。 |
| 🎭 派生仓库合并请求利用 | 可由派生仓库 MR 流水线触达的作业(merge_request_event、only: merge_requests),如果携带机密/权限过宽的 CI_JOB_TOKEN/id_tokens(OIDC),或者在没有 when: manual 门控的情况下执行特权操作(部署/发布/kubectl/terraform),就会被发现。 |
📦 include: 供应链风险 | 从远程 URL 或另一个项目/组件的可变(非 SHA)引用进行 include:——外部流水线代码会被合并到你的流水线中。 |
| ☣️ 制品/缓存投毒 | 不可信作业写入制品/缓存,而有特权的下游作业取用并执行这些内容(通过 needs:/dependencies: 或共享缓存路径)——可导致跨作业甚至跨流水线权限升级。 |
……以及另外五种 CI 系统,同一套污点模型
| 生态系统 | ci-sentinel 可检测的问题 |
|---|---|
🔧 Jenkins(Jenkinsfile) | 来自 params.* / env.CHANGE_* / ghprb* / SCM 数据的命令注入,流入 sh/bat/powershell(通过 environment{} 绑定);凭据泄露(credentials()/withCredentials 被打印或嵌入 GString);Groovy evaluate()/load RCE;缺少 input() 审批关卡;不安全的 agent any。 |
⭕ CircleCI(.circleci/config.yml) | 来自 << pipeline.git.branch/tag >> / 流水线参数的 Shell 注入,流入 run:;未固定版本的 orbs(@volatile / 仅指定主版本号);Fork PR context secret 暴露,且没有 type: approval 关卡;特权部署缺少审批。 |
🟦 Azure Pipelines(azure-pipelines.yml) | 来自 $(Build.SourceBranch) / $(System.PullRequest.SourceBranch) / 提交消息的宏注入,流入 script:/bash:/pwsh:;来自外部仓库资源的不可信 templates;Fork variable-group 密钥暴露;未固定版本的仓库资源。 |
🪣 Bitbucket Pipelines(bitbucket-pipelines.yml) | 来自 $BITBUCKET_BRANCH / $BITBUCKET_TAG / $BITBUCKET_PR_DESTINATION_BRANCH / 提交消息的 Shell 注入,这些值未经引号保护便展开到 script: 中;可由外部触发的 PR 流水线中 secured/deployment-variable 暴露;未固定版本的 pipes(:latest);部署缺少 trigger: manual 关卡。 |
🚦 Travis CI(.travis.yml) | 来自 $TRAVIS_BRANCH / $TRAVIS_PULL_REQUEST_BRANCH / $TRAVIS_COMMIT_MESSAGE 的 Shell 注入,这些值未经引号保护便展开到生命周期钩子中;secure-env PR/Fork 密钥暴露;deploy: 阶段缺少 on: 分支/条件关卡。 |
……另外还有两个单次运行的 Agent 无法复现的深度跨域检测器
| 检测器 | ci-sentinel 可检测的问题 |
|---|---|
| ☁️ OIDC 云信任配置错误(Terraform / CloudFormation / GCP workload-identity / Azure federated-credential) | 对 CI OIDC 的云端部分建模:IAM 角色 / WIF 池 / 联合应用的信任策略。检测带有宽泛通配符(repo:org/*、repo:*)的 sub 条件、完全没有 sub 条件(该颁发者上的任何工作流都能假定该角色)、仓库已固定但 ref/environment 未固定(任何分支都能假定该角色)、裸 pull_request 主体(可由 Fork 触发),或未固定的 aud。随后将 IaC 信任与 CI 侧关联(可从不可信触发器触达并生成 id-token 的工作流),并在整条链路端到端可触达时提升为严重级别。没有任何单文件检查器能检测到这一问题——它横跨 CI 声明和云信任策略。 |
🔧 Jenkins 共享库(@Library → vars/*.groovy) | 跟踪传入共享库全局变量步骤的不可信流水线值(PR 标题 / 分支 / 构建参数),穿过库的 call() 内部,流向内部的 sh/bat 接收点——这是 Jenkins 中与跨文件污点分析(orb/template/composite-action)相对应的检测,仅查看 Jenkinsfile 时无法发现。还会将引用可变引用(分支 / 默认版本)的 @Library 导入标记为供应链风险。 |
每个分析器都了解哪些变量是安全的(SHA、数字 ID、可信 slug——
BITBUCKET_COMMIT、TRAVIS_PULL_REQUEST、pipeline.git.revision、……)以及
哪些 OIDC 信任配置是安全的(sub 固定为 repo:org/repo:ref:refs/heads/main /
:environment:prod,并设置了 aud),因此不会将每个 $VAR 或每项信任配置都标记出来。
加固后的配置中,误报为零。
这是一个真正的静态分析器:解析器会按行处理工作流 YAML → 建模触发器/作业/步骤/权限/操作/输出/依赖关系 → 进行步骤间/作业间污点解析,并检测权限与供应链问题 → 输出评分判定结果,其中每项发现都包含文件:行号、完整污点路径、具体的修复建议,以及可上传到 GitHub 代码扫描的 SARIF 2.1.0 报告(含 codeFlows)。
……而且它不只会标记——还会修复并评分
| 高级版 | 你将获得什么 |
|---|---|
| 🔧 自动修复(精确修正) | 对每项发现,ci-sentinel 都会给出具体修改内容:修正后的 YAML/Groovy 片段以及可直接应用的统一差异——将 action/orb/pipe 固定到不可变的 SHA/版本,将注入的表达式绑定到环境变量并加引号,将全量写入权限降至最小权限,插入手动/审批关卡,固定 OIDC sub/aud,将硬编码密钥移至存储库(并轮换密钥)。不是只说“你有个漏洞”,而是明确指出**“把这个改成那个”**,并标注置信级别(exact / template / guided),让你知道哪些可以直接套用,哪些需要填写具体值。发现会带有稳定的 fingerprint,便于去重;SARIF 结果则包含内联 fixes。 |
| 📋 合规评分卡(A–F) | 采用类似 CIS 的 CI 安全基准,按 A–F 评分,并为每项控制措施提供 PASS / FAIL / WARN / N/A 明细(最小权限、组件固定、不向 fork 泄露密钥、公有 PR 不使用自托管运行器、固定 OIDC、不使用硬编码密钥、不使用 pwn checkout、部署设审批关卡、不存在注入、不存在跨作业投毒)。每项控制措施都会列出影响判定的发现 ID,便于向安全团队说明。可直接利用的严重漏洞会限制评分上限(一个未修复的 RCE/密钥外泄路径就足以主导整体安全态势)。 |
| 🛰️ 实时威胁情报源(数据护城河) | 配置中的每个 uses: / orb / pipe 都会与已知遭入侵 CI 组件的实时服务器端情报源进行比对。情报源通过定时任务从公开来源——OSV.dev 和 GitHub Security Advisory 数据库(ecosystem=actions)——摄取数据,并与精选的标志性事件种子库合并,其中包括 tj-actions/changed-files CVE-2025-30066、reviewdog/action-setup CVE-2025-30154 及其传递依赖项、aquasecurity/trivy-action 标签强制推送事件和 Ultralytics。它能识别 tj-actions/changed-files@v45 是恶意的,并知道同一 action 固定到干净提交的 SHA 或升级至 @v46 后是安全的——静态 YAML 扫描或本地 Linter 无法作出这种区分,因为它们没有情报源。情报源仅存于托管服务端(轻量客户端不会携带它);GET /feed/status 可显示其最新状态。实时信誉信号(星标数 / 最近提交时间 / 是否已归档 / 仓库是否仍可解析)还会标记已归档/已弃用的组件,以及可能成为接管目标的失效引用。**这就是支撑托管付费模式的准入护城河:**价值来自实时数据,而非计算能力。 |
| 🪤 标签重写与冒名检测(实时引用→提交) | 向 ci-sentinel 提供你预期可变引用指向的提交 SHA(来自锁定文件/SBOM),它就会解析该标签在上游当前指向的对象,并标记标签重写/强制推送(@v2 现在运行的提交与审核过的不同——这正是 tj-actions 攻击的手法)、已删除/失效的引用或近期出现的可疑变更。它还会结合实时信誉信号进行拼写仿冒检测,确认是否存在冒名行为——例如 actons/checkout(与 actions 近似但拼错),其仓库是刚创建、星标很少或已失效的冒名仓库——并将其与名称真实但规模较小的 fork 区分开来(不产生误报)。此外,由于情报源以组件身份为索引,无论哪个 CI 系统引用了受感染的 action,都能检测出来(跨 CI);这是单一 CI 扫描器在结构上无法具备的能力。 |
MCP 服务(免费)
{
"mcpServers": {
"ci-sentinel": { "command": "npx", "args": ["-y", "ci-sentinel-mcp"] }
}
}
工具:audit_ci_security。传入 files(工作流文件名 → YAML 的映射)或
source(单个工作流)。免费版会返回判定结果,以及发现的各类问题
数量。
深度审计(deep: true)——两种付费方式
深度审计会返回每项发现及其文件和行号、完整的步骤间/作业间注入污染路径、传递式 Action 供应链图、每项发现对应的具体修复方案(修正后的代码片段 + 统一差异)、包含各项控制措施明细的 A–F 合规评分卡,以及带内联 fixes 的 SARIF 2.1.0 文档(可通过 github/codeql-action/upload-sarif 上传到 GitHub 代码扫描)。
- 💳 银行卡(Stripe)——在
https://ci-sentinel.vercel.app/pro/checkout购买预付密钥,然后在 MCP 配置中设置"env": { "CI_SENTINEL_KEY": "<key>" }。 - 🪙 x402(USDC)——AI Agent 自动按次调用付费(使用 Base 上的 USDC),无需注册。
HTTP API
POST /audit # free, rate-limited — verdict + per-severity counts
POST /pro/audit # deep — pay-per-call (x402) or Authorization: Bearer <key>
POST /mcp # MCP-over-HTTP (free)
GET /presence # live active sessions (last 5 min)
GET / # this landing page
curl -X POST https://ci-sentinel.vercel.app/audit \
-H 'Content-Type: application/json' \
-d '{"files":{".github/workflows/ci.yml":"name: CI\non: pull_request_target\n..."}}'
为什么托管?(护城河)
npm 包是一个精简客户端:不会在本地运行任何分析。解析器、污点引擎、Action 图解析器和检测器知识库仅在服务端运行,置于付费墙之后——因此,付费内容(发现、证据、污点路径、修复建议)绝不会出现在调用方的机器上。npm pack 只会打包 dist/mcp.js、dist/mcpServer.js 和 dist/types.js;引擎不会进入 tarball(由 npm run test:moat 自动验证)。
实时动态的情报源如何保持更新(更新管道)
威胁情报源通过摄取更新,而非硬编码。服务端会运行一个定期任务:
- 获取来自两个公开来源的公告(无需付费密钥):
- GitHub Security Advisory DB——
GET /advisories?ecosystem=actions(公开;GITHUB_TOKEN仅会提高速率限制,并非必需)。 - OSV.dev——查询
GitHub Actions生态系统中我们已跟踪的组件,以及 GHSA 刚刚披露的所有组件(由此让 OSV 补充相关信息)。
- GitHub Security Advisory DB——
- 规范化每条公告并转换为
ThreatRecord——拆分所有者和名称、根据公告文本推断事件类别(标签重写/维护者遭入侵/恶意行为/CVE……)、划分严重性等级、将受影响版本范围解析为选择器,并记录修复版本(因此升级后的固定版本不会触发告警)。 - 合并记录并写入精选种子数据(
ingestFeed:合并引用、保留最高严重性、扩大受影响范围,并按标识去重)。 - 存储快照到 Cloudflare KV。每次
/pro/audit都会通过kvFeedProvider读取快照;如果 KV 尚无数据,则回退到编译时内置的种子数据,确保检测器始终可用,且检测效果不会差于静态基线。
# run the refresh once (live: hits the real public APIs)
node scripts/refreshFeed.mjs
# dry run with no network (produces the seed-only snapshot)
CI_SENTINEL_NO_NET=1 node scripts/refreshFeed.mjs
可通过 Vercel Cron({ "path": "/internal/refresh-feed", "schedule": "0 */6 * * *" },由 FEED_REFRESH_TOKEN 进行保护)或运行 node scripts/refreshFeed.mjs 的定时 GitHub Action 来安排任务。GET /feed/status 会报告实时快照的版本、generatedAt 和记录数量——这是公开的新鲜度证明。这些内容都不会随 npm 客户端一起发布。
开发
npm install
npm run build # tsc
npm test # engine + parser + taint + SARIF + autofix + compliance + corpus tests (851 checks)
npm run test:moat # lock-proof: tarball ships no engine, deep degrades w/o pay
npm run dev:http # local HTTP server (FORCE_LISTEN)
对你提供的工作流 YAML 进行启发式静态分析——它无法查看仓库级别的默认令牌权限、分支保护或组织策略,也不会执行管道。请将发现视为需要核实的线索。
源码和文档:https://github.com/Baneado98/ci-sentinel · MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。