Lifecycle actions and DELETE are allowed on containers that no policy covers
维护者通常 1 天内回复
已经有一个关联 PR 被合并了。
- #90 来自 @abienkowski —— 已合并
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 25/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 停滞
- 技术栈
- docker, go, rust, typescript
- 领域
- api, authorization, security
调研方向
Start with routeByContainerName in go/internal/proxy/router.go (lines 158-170), where a failed manager.Get(name) still returns ActionAllow; the Rust and TypeScript routers have the same branch. The spec/README.md rows realNameDeleteAllowed, execPrefixNameStartAllowed and execPrefixNameDeleteAllowed pin the current behavior. Done means unknown targets return 403 across all three implementations, the tests and Quint model match, and open design questions are settled. PR #90 is already open against this issue, so check it before starting.
由索引模型根据 Issue 内容生成。
描述
Describe the bug
The proxy forwards start, stop, restart, kill, wait, pause, unpause and DELETE for any container name, including names that no loaded policy covers. The README says these endpoints are "Allowed on known containers" (README routing table, lines 214-215). The code, the tests and the Quint router model all allow unknown containers on purpose (spec/README.md row realNameDeleteAllowed: "allow (unknown container)"). So the README and the implementation disagree.
The effect: every caller of a socket can stop or delete every container on the host, not only the containers its policies describe. On a host that also runs operator containers (monitoring, Watchtower, log shippers), a contributor can stop or remove them. The trust model bounds a caller to the union of the socket's policies. Containers outside every policy are outside that union, so this is wider than the documented trust boundary.
Affected implementation(s)
- Go
- Rust
- TypeScript
- All
Go go/internal/proxy/router.go routeByContainerName (lines 158-170): if manager.Get(name) fails, it still returns ActionAllow. Rust and TypeScript have the same branch, and their router tests assert it.
To Reproduce
-
Policy:
service_name: beacon allowed_image_prefixes: [chainsafe/lodestar] -
Directly on the daemon (not through the proxy):
docker run -d --name dsp-monitoring alpine:3.20 sleep 1d -
With
DOCKER_HOSTpointed at the proxy socket, run each command:Command Container state after Audit log docker stop -t 1 dsp-monitoringexitedPOST /v1.56/containers/dsp-monitoring/stop?t=1 ALLOWdocker start dsp-monitoringrunningPOST /v1.56/containers/dsp-monitoring/start ALLOWdocker kill <full 64-hex id>exitedPOST /v1.56/containers/f4b4ac3e…fee2/kill ALLOWdocker rm dsp-monitoringremoved DELETE /v1.56/containers/dsp-monitoring ALLOWI expected
403for each.
Expected behavior
Default-deny, the same as the rest of the router: forward a lifecycle action or DELETE only if the target belongs to a loaded policy. Otherwise return 403.
Points to decide:
- How a target matches a policy. Today
manager.Get(name)matches onservice_name. After #85,container_namesis the better key, because one image can serve several names. - Container IDs. Callers often use an ID instead of a name, and Ansible
community.dockerdoes. The proxy needs to resolve the ID to a name (oneGET /containers/{id}/jsonto the daemon) before it decides. - Test rows.
realNameDeleteAllowed,execPrefixNameStartAllowedandexecPrefixNameDeleteAllowedchange from allow to deny. The Quint router model changes too.
If allow-unknown is the intended behavior, the README routing table needs to say so, and the Trust model section needs to say that every caller can stop or delete every container on the host.
Environment
- OS: OrbStack, Linux arm64
- Docker version: Engine 29.8.2 (API 1.56), CLI 29
- Implementation version/commit: v0.3.11 (
3130b0a), Godocker-socket-policy-go-linux-arm64
Additional context
First seen with the request probe from ChainSafe/lodestar-infrastructure#73 (not merged), while checking the proxy design in ChainSafe/lodestar-infrastructure#9. Seven of its checks fail on this behavior. The table above is from a real daemon. A related create-time gap: a create named monitoring with an allowed image is also accepted. #85's "exactly one match, otherwise deny" closes that gap if every policy sets container_names.
- 主要语言
- Rust
- 星标
- 2
- 派生
- 0
- 平均合并
- 12 小时 11 分钟
- 30 天内合并 PR
- 30
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
ChainSafe/docker-socket-policy 的其他 Issue
-
Type: Feature
难度 5/5 一周以上 新手友好度 12/100
ChainSafe/docker-socket-policy#96 ·
维护者通常 1 天内回复
-
Priority: P3 Type: Enhancement
难度 4/5 3-5 天 新手友好度 15/100
ChainSafe/docker-socket-policy#95 ·
维护者通常 1 天内回复
-
Type: Feature
难度 5/5 一周以上 新手友好度 25/100
ChainSafe/docker-socket-policy#65 ·
维护者通常 1 天内回复
-
Type: Enhancement
难度 5/5 一周以上 新手友好度 38/100
ChainSafe/docker-socket-policy#46 · 1 条评论 ·
维护者通常 1 天内回复
查看 ChainSafe/docker-socket-policy 的全部 Issue
相似的 Issue
-
area: compat area: parsing bug
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
OFN writer emits `DocIRI` as a bare IRI, which becomes a version IRI or a parse error on re-read未关闭
难度 2/5 1-3 小时 新手友好度 72/100
phillord/horned-owl#338 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
type/bug
难度 2/5 1-3 小时 新手友好度 72/100
stackabletech/operator-rs#1301 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 62/100
jmcnamara/rust_xlsxwriter#205 · 4 条评论 ·