tmatens/container-security-profiles

GitHub: tmatens/container-security-profiles

一个基于降权测试和 eBPF 观察推导出的容器镜像最低安全权限配置文件目录,帮助用户精确裁剪每个镜像的 capabilities 和文件系统权限。

Stars: 1 | Forks: 0

# container-security-profiles [![validate](https://static.pigsec.cn/wp-content/uploads/repos/cas/8b/8bac9b2d4451308c2328a394489786931947b63f84293ce8605e6f4e04ad0860.svg)](https://github.com/tmatens/container-security-profiles/actions/workflows/validate.yml) [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) **有证据支撑的容器镜像最低安全配置文件** — 即每个镜像*实际需要*的 capabilities 和只读文件系统配置, 这些是 通过逐一移除权限并证明容器在没有它们的情况下会崩溃而得出的。 这不是从博客文章中抄来的指南:每个配置文件都固定了摘要(digest-pinned),有专门的已提交工作负载脚本支持,并在文件中包含了完整的推导证据。 例如,immich 附带的 postgres 在 `cap_add` 中包含了 `FOWNER` — 而 经过推导和降权测试(drop-tested)得出的最低需求是四个 capabilities,因此 `FOWNER` 属于明显的过度授权: ``` services: postgres: image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0 cap_drop: [ALL] cap_add: [CHOWN, DAC_OVERRIDE, SETGID, SETUID] security_opt: ["no-new-privileges:true"] ``` ## 目录 | Image | Tags | Dimension | Minimum | Confidence | |---|---|---|---|---| | `codeberg.org/forgejo/forgejo` | `15` | capabilities | `cap_add: [CHOWN, DAC_OVERRIDE, SETGID, SETUID, SYS_CHROOT]` | high | | `docker.io/grafana/alloy` | `v1.16.2` | filesystem | `read_only: true` | high | | `docker.io/grafana/grafana` | `13.0.2` | filesystem | `read_only: true` | moderate | | `docker.io/grafana/loki` | `3.7.2` | filesystem | `read_only: true` | high | | `docker.io/library/caddy` | `2` | capabilities | `cap_add: [NET_BIND_SERVICE]` | high | | `docker.io/library/caddy` | `2` | filesystem | `read_only: true` | high | | `docker.io/library/mariadb` | `11.4` | capabilities | `cap_add: [SETGID, SETUID]` | high | | `docker.io/library/postgres` | `16` | capabilities | `cap_add: [CHOWN, DAC_OVERRIDE, SETGID, SETUID]` | high | | `docker.io/library/redis` | `8.2.7` | capabilities | `cap_add: [SETGID, SETUID]` | high | | `docker.io/library/postgres` | `16` | filesystem | `read_only: true, tmpfs: [/run/postgresql]` | high | | `docker.io/netdata/netdata` | `v2.10.3` | capabilities | `cap_add: [DAC_OVERRIDE, SETGID, SETUID, SYS_PTRACE]` | high | | `docker.io/valkey/valkey` | `9` | capabilities | `cap_add: [SETGID, SETUID]` | high · app-tier ✓ | | `ghcr.io/gethomepage/homepage` | `v1.13.2` | filesystem | `read_only: true, tmpfs: [/app/.next/cache]` | high | | `ghcr.io/home-assistant/home-assistant` | `2026.7.1` | capabilities | `cap_add: [DAC_OVERRIDE]` | high | | `ghcr.io/immich-app/postgres` | `14-vectorchord…` | capabilities | `cap_add: [CHOWN, DAC_OVERRIDE, SETGID, SETUID]` | high · app-tier ✓ | 所有的 capability 配置文件都是 `cap_drop: [ALL]` 加上列出的 `cap_add`。 **[可浏览的目录网站](https://tmatens.github.io/container-security-profiles/)** 渲染了每一个配置文件及其可直接复制的代码片段、降权测试证据表、 记录的调用过程和评估标准 — 或者您可以直接阅读 [`catalog/`](catalog/) 下的 YAML 文件。 想要添加某个镜像?[请求配置文件](../../issues/new?template=profile-request.yml)。 ## 使用配置文件 **直接使用:** 将对应的维度(dimension)复制到您的 compose 文件中(网站上的每个配置文件页面都有现成的代码片段)。需要注意一个重要事项:配置文件是**针对所记录的调用**(即配置文件中的 `run_config` 块)的最低要求。不同的 `user:`、预初始化与全新数据卷的区别,或者覆盖 entrypoint,都会改变最低需求。在采用之前,请阅读配置文件的 `criteria/` 文档;如果配置文件导致您的部署崩溃, 请[报告不匹配情况](../../issues/new?template=profile-mismatch.yml)。 **通过 compose-lint**(可选的实验性预览):将 [compose-lint](https://github.com/tmatens/compose-lint) ≥ 0.13 指向此目录的一个克隆版本,其检查结果将获得针对特定镜像的指导建议: ``` # .compose-lint.yml profiles: enabled: true path: /path/to/container-security-profiles/catalog ``` ``` CL-0006 Service does not drop all capabilities. … fix: … profile hint (csd-derived, confidence high, from docker.io/library/postgres@sha256:fe03a76…, tag match — compose-lint can't see your runtime, confirm it fits your setup): observed minimum is cap_drop: [ALL] + cap_add: [CHOWN, DAC_OVERRIDE, SETGID, SETUID] ``` 增强(Enrichment)功能仅供参考 — 它绝不会创建、删除或重新分类任何 检查结果,并且仅消耗 `validated` 状态的配置文件。 ## 为什么信任这些配置文件 每个 `validated` 状态的配置文件都通过了机器检查的门槛(CI 会在每次 更改时运行它;`make validate` 会在本地运行相同的检查): - **模式有效**:符合版本化的 compose-lint profile schema,该 schema 是在验证时从固定的 compose-lint commit(`contract/compose-lint.ref`)中获取的 — 没有容易发生漂移的本地拷贝。 - **摘要固定(Digest-pinned)**:`validated_image` 记录了产生证据所依据的确切 `…@sha256:…`,并且 `applies_to.tags` 只能固定**不可变的版本标签(immutable version tags)** — 基于 `latest` 标签推导出的配置文件是毫无意义的。 - **工作负载支持**:测试脚本已提交在 [`profiles/workloads/`](profiles/workloads/) 下并经过了哈希验证 (`workload_sha256`)。工作负载会执行镜像的实际功能并断言权限被降低 (仅靠健康检查是不够的)。 - **证据记录在文件中**,根据推导方法分为: - **drop-test** — 每个授予的元素被依次移除,容器重启,工作负载重新验证;每个元素的结果就是配置文件中 `drop_test.checks` 表的内容。这可以捕获*仅在启动时需要的*最低权限(例如数据目录的 `chown`,root→user 的权限降级),而这些是运行时观察在结构上无法发现的。目前整个目录都是通过这种方式推导出来的。 - **bpf-observation** — 对正在运行的工作负载进行超过 300 秒的实时 eBPF 观察。 - **App-tier verified**(如已标记):这种加固已在*服务*级别得到了额外验证 — 即在应用最低权限的情况下启动完整技术栈,并通过其实际 API 进行驱动测试,其中包括一次过度加固探测,用于表明该检查能够捕获过于严格的配置。 - **新鲜度跟踪**:每周一次的 `staleness` workflow 会将每个固定的摘要与该标签当前发布的摘要进行比对,一旦发现偏差(drift)就会创建一个跟踪 issue,标记该配置文件需要重新推导。 **信任模型:** 认可(`validated`)的配置文件是由维护者自动化工具推导并且可以重新推导的。外部贡献在被重现之前,只会以 `exploratory` 状态(仅供参考,绝不用于增强功能)合并 — 请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。 ## 布局 目录和评估标准路径采用了 registry 命名空间 (`//`),这与完全限定的镜像引用保持一致。 - `catalog/….yaml` — 已验证的配置文件;`catalog/exploratory/…` — 未达到推广标准的草稿。 - `criteria/….md` — 每个镜像的场景和通过标准。 - `profiles/workloads/*.sh` — 已提交的测试脚本。 - `derivation/manifest.yaml` — 重新推导规范:如何具代表性地重新推导每个 配置文件(镜像、维度、方法、工作负载)。 - `contract/compose-lint.ref` + `scripts/fetch-contract.sh` — 固定的 schema/validator 契约(获取到 `.contract/` 目录下,已被 gitignored)。 - `scripts/check_staleness.py` — 仅基于 registry 的摘要漂移检查。 - `scripts/build_site.py` — 静态目录网站生成器 (`make site`;由 `.github/workflows/pages.yml` 部署)。 ## 验证 ``` pip install -r requirements.txt make validate # fetches the pinned contract, then validates the catalog ``` CI 会在每次 PR 和推送到 main 分支时运行相同的检查,此外还会对 目录网站进行一次冒烟构建。 ## 与 compose-lint 的关系 这是 compose-lint [ADR-017](https://github.com/tmatens/compose-lint/blob/main/docs/adr/017-security-profile-catalog.md) 中描述的外部配置文件目录: 两者仅通过唯一的东西联系在一起 — 版本化的 profile schema。 compose-lint 提供了 schema、loader 和 validator,但**没有配置文件**;而此 目录提供了配置文件,但没有代码依赖。数据是单向流动的(目录 → 消费者),并且消费行为是可选的。它的名称有意保持消费者中立: compose-lint 是第一个消费者,但不是唯一可能的消费者。 ## 配置文件是如何推导出来的 配置文件由 **container-sec-derive (csd)** 推导出来 — 这是一个运行时工具, 通过 eBPF 观察正在运行的容器(capabilities、文件系统写入、 设备、出口流量),并针对实际工作负载对候选的最低权限进行降权测试(drop-test)。 csd 尚未发布;在发布之前,每个配置文件都携带了足够的证据 (`run_config`、工作负载脚本、逐元素的降权测试结果)以便使用任何测试工具重现其推导过程:应用配置文件,运行工作负载,移除其中一个元素,观察它是如何崩溃的。 ## 贡献 欢迎提交配置文件请求、不匹配报告和配置文件贡献 — 请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。安全策略: [SECURITY.md](SECURITY.md)。 ## 许可证 [MIT](LICENSE)。配置文件属于数据 — 在注明出处的情况下可自由重复使用。
标签:DevSecOps, Docker, Docker镜像, Web截图, 上游代理, 安全基线, 安全测试, 安全防御评估, 容器安全, 攻击性安全, 教学环境, 最小权限原则, 版权保护, 逆向工具