核心是将ci权限决策从代码层上移至平台与基础设施层:强制隔离执行环境、阻断剧本篡改链路、运行时权限熔断、全量审计留痕。

核心思路是切断“开发人员直接控制 Runner 执行环境”的路径,把权限决策从代码层(.gitlab-ci.yml)上提到平台层和基础设施层。单纯靠 YAML 文件校验或角色权限分配无法防范恶意修改 CI 脚本的行为——因为项目维护者天然有权提交该文件。
隔离执行环境:强制使用无特权、一次性容器
Runner 必须禁用 shell executor,只启用 docker 或 kubernetes 类型,并配置为:
-
禁止 privileged 模式:所有 job 容器启动时不得带
--privileged参数 -
默认只读根文件系统:通过
read_only: true+ 显式挂载/tmp等必要可写路径 -
禁止挂载宿主机敏感路径:如
/var/run/docker.sock、/proc、/sys、/etc等一律禁止 bind mount -
使用非 root 用户运行容器:在
image中指定user: 1001,或在 job 中用user:覆盖
阻断剧本篡改链路:保护 .gitlab-ci.yml 的可信来源
不依赖“谁写的 YAML”,而依赖“YAML 是否经可信流程签发”:
批量替换指定目录下所有 Git 仓库的远程地址(remote URL)。 当用户需要将 Git 仓库从一个服务器迁移到另一个服务器时使用。 触发词:git remote 替换、git url 批量修改、git 仓库迁移、更换 git 地址、批量修改 remote url。
-
禁用项目级自由编辑:将
.gitlab-ci.yml移出项目仓库,改为由中央 CI 模板库统一托管(如gitlab-org/ci-templates),项目仅通过include:引用已签名的版本 -
启用 include 验证机制:配置 GitLab 实例启用
include_validation(GitLab 16.10+),要求被 include 的 YAML 必须来自受信项目且经 GPG 签名 - 保护模板库访问权限:模板库设为 private,仅允许 CI 管理员组(非开发人员)推送;合并请求需双人审批 + 自动化签名验证流水线
运行时权限熔断:ID Token + 外部策略引擎联动
让每个 job 在真正执行前,向可信服务做动态授权检查:
-
启用 GitLab ID Token:在 job 中通过
$CI_JOB_JWT获取短期、作用域受限的 JWT,包含触发者身份、项目 ID、ref、job stage 等上下文 - 对接外部策略服务(如 Open Policy Agent):Runner 启动 job 前,调用本地 OPA agent,传入 JWT 和 job 元数据,执行策略判断(例如:“维护者不能在 deploy stage 运行 docker:dind”)
-
拒绝高危操作硬编码:在策略中明确定义黑名单命令(
docker run --privileged、nsenter、mount --bind、chroot等),匹配 script 字段内容即拦截
审计与纵深防御:不可绕过的操作留痕
即使攻击者突破某一层,也要确保行为可追溯、不可抵赖:
-
开启全量 CI 审计日志:在 Admin Area → Settings → Network → Audit Events 中启用
CI/CD pipeline events,记录 job 触发者、原始 ref、实际执行的 script 内容哈希、容器镜像 digest -
Runner 日志强制落盘到独立审计节点:Runner 配置
log_level: debug并通过syslog或filebackend 输出到只读 NFS 或 Loki 集群,开发人员无法删除或覆盖 -
部署 eBPF 安全监控(可选):在 Runner 宿主机部署 Tracee 或 Falco,实时检测异常进程调用(如非 dockerd 进程调用
clone()创建新命名空间)、可疑文件写入(如写入/etc/cron.d/)










