srini-cybersec/containershield
GitHub: srini-cybersec/containershield
一款纯离线的容器配置静态安全扫描器,通过 34 条 CIS 映射规则检测 Dockerfile、Compose 和 Kubernetes 清单中的配置错误。
Stars: 0 | Forks: 0
# 🛡️ ContainerShield
[](https://github.com/srini-cybersec/containershield/actions/workflows/ci.yml)
[](https://www.python.org/)
[](LICENSE)
[](#testing)
[](#detection-rules)
ContainerShield 是一款**纯 Python、完全离线**的静态分析工具,专门用于分析定义容器供应链的配置文件。它能够解析 Dockerfiles、`docker-compose.yml` 以及 Kubernetes manifests,随后会评估 **34 条检测规则**,这些规则映射了 **CIS Docker & Kubernetes Benchmarks**、NSA/CISA 加固指南以及 CWE 标识符。
它执行 **零网络调用**,绝不运行其扫描的内容,并会对发现的任何 secret 进行脱敏处理 —— 这使得它可以安全地集成到 CI 或气隙管道中。
## 为什么选择 ContainerShield?
容器配置错误是导致云环境被攻破最常见 —— 也最容易被预防 —— 的原因之一:例如一个设置了 `privileged: true` 的 pod、挂载了 Docker socket、使用了 `:latest` 的基础镜像,亦或是被硬编码到镜像层中的 `AWS` 密钥。其中大多数问题在部署之前的*配置文件*中就已经清晰可见了。
ContainerShield 能够在最早的时机 —— **在编写代码时和 CI 阶段**,也就是在镜像构建或 pod 调度之前 —— 就将它们捕获。
- ✅ **一个工具,三种方言** — 通过单一的标准化引擎支持 Dockerfile、Compose 和 Kubernetes。
- ✅ **气隙安全** — 没有 daemon,没有 API,没有遥测,没有网络请求。
- ✅ **CI 原生** — 生成用于 GitHub Code Scanning 的 SARIF 2.1.0 + 支持 `--fail-on` 门禁拦截。
- ✅ **可解释性** — 每个发现都包含 CWE、CIS 控制、脱敏后的证据以及修复建议。
## 架构
```
flowchart LR
A[Files / dirs] --> B[Detect type]
B --> C1[Dockerfile parser]
B --> C2[Compose parser]
B --> C3[K8s parser]
C1 & C2 & C3 --> D[Rule engine\n34 CIS-mapped rules]
D --> E[Scoring 0-100\n+ verdict]
E --> F[console / json / csv / sarif / html]
E --> G{--fail-on}
G -->|exceeded| X[exit 1]
```
完整设计请参阅 [`docs/architecture.md`](docs/architecture.md)。
## 安装
```
# From source
git clone https://github.com/srini-cybersec/containershield.git
cd containershield
pip install -e .
# 或者引导一个开发环境(venv + dev deps + tests)
./scripts/setup.sh
```
要求 **Python 3.11+**。运行时依赖项:`click`、`rich`、`PyYAML`、`Jinja2`。
## 用法
```
# 扫描单个文件(自动检测 type)
containershield scan Dockerfile
# 递归扫描整个项目目录
containershield scan ./deploy/
# 为 GitHub Code Scanning 输出 SARIF
containershield scan ./deploy/ -f sarif -o results.sarif
# 如果存在任何 HIGH+ issue 则使 CI job 失败
containershield scan ./deploy/ --fail-on HIGH
# 仅显示 critical issue,并排除一个 noisy rule
containershield scan Dockerfile --min-severity CRITICAL --exclude-rule CS-DKR-006
# 强制将文件视为特定的 type
containershield scan my.tmpl --target kubernetes
# 列出每个 built-in rule
containershield rules
containershield rules --target kubernetes --json
```
### 输出示例
```
ContainerShield Findings
┏━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Severity ┃ Rule ┃ Location ┃ Issue ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ CRITICAL │ CS-CMP-001 │ compose.yml (web) │ Service runs in privileged │
│ │ │ │ mode… │
│ CRITICAL │ CS-CMP-003 │ compose.yml (web) │ Mounts the Docker daemon │
│ │ │ │ socket… │
│ HIGH │ CS-CMP-002 │ compose.yml (web) │ Host network namespace… │
└────────────┴────────────┴───────────────────┴────────────────────────────────┘
╭──────────────────────────── Summary ────────────────────────────╮
│ Files scanned: 1 CRITICAL: 4 HIGH: 2 MEDIUM: 3 LOW: 1 │
│ Risk score: 100/100 Verdict: CRITICAL │
╰──────────────────────────────────────────────────────────────────╯
```
## 检测规则
ContainerShield 内置了跨越三个类别的 **34 条规则**。完整列表请使用:`containershield rules`。
### Dockerfile (`CS-DKR-*`, 11 条规则)
| ID | 严重性 | 检查内容 | CIS |
|----|----------|-------|-----|
| CS-DKR-001 | HIGH | 容器以 root 用户运行(无非 root 的 `USER`) | 4.1 |
| CS-DKR-002 | MEDIUM | 基础镜像使用了可变标签 / `:latest` | 4.2 |
| CS-DKR-003 | LOW | 使用了 `ADD` 而非更安全的 `COPY` | 4.9 |
| CS-DKR-004 | HIGH | 远程脚本通过管道传递给 shell(`curl \| bash`) | 4.7 |
| CS-DKR-005 | CRITICAL | 在 `ENV` / `ARG` 中硬编码了 secret | 4.10 |
| CS-DKR-006 | LOW | 未定义 `HEALTHCHECK` | 4.6 |
| CS-DKR-007 | MEDIUM | 通过 `sudo` 提升权限 | 4.1 |
| CS-DKR-008 | MEDIUM | 全局可写权限(`chmod 777`) | 4.1 |
| CS-DKR-009 | LOW | 安装包时未锁定版本 | 4.2 |
| CS-DKR-010 | MEDIUM | 暴露了敏感端口(SSH/RDP/Docker API) | 4.1 |
| CS-DKR-013 | MEDIUM | `ADD` 获取远程 URL(无校验和) | 4.9 |
### Docker Compose (`CS-CMP-*`, 10 条规则)
| ID | 严重性 | 检查内容 | CIS |
|----|----------|-------|-----|
| CS-CMP-001 | CRITICAL | 特权容器 | 5.4 |
| CS-CMP-002 | HIGH | host 网络模式 | 5.9 |
| CS-CMP-003 | CRITICAL | 挂载了 Docker socket | 5.31 |
| CS-CMP-004 | HIGH | 添加了危险 capability(`SYS_ADMIN`, …) | 5.3 |
| CS-CMP-005 | HIGH | 共享了 host PID/IPC namespace | 5.15 |
| CS-CMP-006 | LOW | 根文件系统可写 | 5.12 |
| CS-CMP-007 | MEDIUM | 未设置 `no-new-privileges` | 5.25 |
| CS-CMP-008 | HIGH | 绑定挂载了敏感的 host 路径 | 5.5 |
| CS-CMP-009 | CRITICAL | 在 `environment` 中硬编码了 secret | 5.10 |
| CS-CMP-010 | MEDIUM | 容器以 root 用户运行 | 5.9 |
### Kubernetes (`CS-K8S-*`, 13 条规则)
| ID | 严重性 | 检查内容 | CIS |
|----|----------|-------|-----|
| CS-K8S-001 | CRITICAL | 特权容器 | 5.2.1 |
| CS-K8S-002 | HIGH | `allowPrivilegeEscalation` 未设置为 `false` | 5.2.5 |
| CS-K8S-003 | HIGH | 可能以 root 运行(无 `runAsNonRoot`) | 5.2.6 |
| CS-K8S-004 | HIGH | `hostNetwork: true` | 5.2.4 |
| CS-K8S-005 | HIGH | 共享了 `hostPID` / `hostIPC` | 5.2.2 |
| CS-K8S-006 | HIGH | 挂载了 `hostPath` 卷 | 5.2.4 |
| CS-K8S-007 | HIGH | 添加了危险 capability | 5.2.9 |
| CS-K8S-008 | MEDIUM | 根文件系统可写 | 5.2.11 |
| CS-K8S-009 | MEDIUM | 缺少 CPU/内存限制 | 5.7.3 |
| CS-K8S-010 | MEDIUM | 镜像使用了可变标签 | 5.5.1 |
| CS-K8S-011 | LOW | 自动挂载 Service account token | 5.1.6 |
| CS-K8S-012 | HIGH | RBAC 通配符权限 | 5.1.3 |
| CS-K8S-013 | MEDIUM | 暴露了 `hostPort` | 5.2.4 |
## 配置
优先级(最高者生效):**CLI 标志 → 环境变量 → 配置文件 → 默认值**。
`.containershield.yml`:
```
min_severity: INFO # suppress findings below this severity
fail_on: HIGH # exit 1 if any finding at/above this severity
exclude_rules:
- CS-DKR-006 # e.g. ignore missing HEALTHCHECK
```
环境变量:
```
export CONTAINERSHIELD_MIN_SEVERITY=MEDIUM
export CONTAINERSHIELD_EXCLUDE_RULES=CS-DKR-006,CS-CMP-006
export CONTAINERSHIELD_FAIL_ON=CRITICAL
```
## 输出格式
| 格式 | 标志 | 用例 |
|---------|------|----------|
| Console | `-f console` | 人类可读的 Rich 表格(默认) |
| JSON | `-f json` | 机器解析 / 管道 |
| CSV | `-f csv` | 电子表格 / 工单系统 |
| SARIF | `-f sarif` | GitHub Code Scanning,IDE 集成 |
| HTML | `-f html` | 可分享的高管报告 |
风险评分映射到相应的结论:**CRITICAL** (≥80 或存在任何 critical 发现),**HIGH_RISK** (≥50 或存在任何 high 发现),**MODERATE** (≥25),**LOW_RISK** (>0),**CLEAN** (0)。
## Docker
扫描器以经过加固的非 root 镜像形式发布:
```
docker build -t containershield .
# 扫描一个 mounted 的项目,完全 sandboxed(无网络、read-only、无 caps)
docker run --rm --network none --read-only \
-v "$PWD:/project:ro" containershield scan /project
```
或者通过 Compose:
```
docker compose run --rm containershield scan /project
```
镜像加固:非 root **UID 10001**、`read_only`、`cap_drop: ALL`、`no-new-privileges`、`network_mode: none`。
## GitHub Actions 集成
```
- name: ContainerShield scan
run: |
pip install containershield
containershield scan . -f sarif -o containershield.sarif --fail-on HIGH
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: containershield.sarif
```
## 测试
```
pytest tests/ -v --cov=src --cov-report=term-missing
```
- **102 个测试**,**97% 覆盖率**
- `black`、`ruff`、`mypy` 检查无误;`bandit` 报告 **零** 发现
- CI 会在 Python 3.11 和 3.12 上运行完整的门禁拦截,构建 Docker 镜像,并自检 sample manifests
## 安全考量
- **完全被动且离线。** ContainerShield 仅解析配置;它绝不会构建镜像、运行容器或联系任何网络 endpoint。运行它不需要任何授权。
- **Secret 脱敏。** 检测到的凭据在任何报告中出现之前都会被脱敏(仅保留一小段前缀用于分诊)。
- **防御性解析。** 格式错误或恶意的文件会记录为解析错误并被跳过 —— 它绝不会中止扫描或执行代码。
- **静态分析不能替代**运行时准入控制(例如 Pod Security Standards、OPA/Gatekeeper)或镜像漏洞扫描。请将 ContainerShield 用作安全左移的第一道防线。
## License
[MIT](LICENSE) © 2026 srini-cybersec
标签:Docker, Web截图, 子域名突变, 安全防御评估, 容器安全, 版权保护, 请求拦截, 逆向工具, 错误基检测, 静态代码分析