KinohTaGo/cc-cleanroom

GitHub: KinohTaGo/cc-cleanroom

为 Claude Code CLI 提供可复现的摘要固定隔离容器,附带运行时验证器以消除环境漂移对运行结果的影响。

Stars: 0 | Forks: 0

# cc-cleanroom [![container-image-build](https://static.pigsec.cn/wp-content/uploads/repos/cas/fd/fdf950e825c08a88400a07c1fe976491f60e26edb0be056b357a8b1c02707794.svg)](https://github.com/KinohTaGo/cc-cleanroom/actions/workflows/container-image-build.yml) 一个用于运行 Claude Code CLI 的可复现的干净环境容器(clean-room container),因此一次运行的结果取决于你选择的输入,而不是运行它的机器。 ``` docker pull ghcr.io/kinohtago/cc-cleanroom:latest docker run --rm ghcr.io/kinohtago/cc-cleanroom:latest verify_clean_room.sh ``` ## 为什么 在开发者笔记本电脑上运行的 CLI 会继承一个庞大且不可见的环境:全局的 `CLAUDE.md`、已安装的插件、会话钩子(hooks)、内存目录、shell 别名,以及 上次自动更新的任何 CLI 版本。其中任何一个都可能改变结果。 这使得两个常见任务变得不可靠: - **比较两次运行。** 如果运行 A 和运行 B 是在不同的机器上执行的——或者在同一台 机器上相隔一周——输出的差异不能说明任何问题。 - **以后复现一次运行。** 如果产生它的环境不再存在,“它在五月的行为是这样的”这种说法就是无法证伪的。 这个镜像移除了这个表面因素,并固定(pin)了剩余的内容。 ## 固定了什么,以及如何固定 | 层级 | 机制 | |---|---| | 基础镜像 | 通过**清单列表摘要**(manifest-list digest)而非标签固定的 `node:20-slim`。多架构:相同的摘要可在 `linux/amd64` 和 `linux/arm64` 上解析。 | | CLI | 精确版本(`@anthropic-ai/claude-code@X.Y.Z`)。没有 semver 范围。被撤回的版本会导致构建失败,而不是静默解析为其他内容。 | | HOME | `/cleanroom`,空的。没有 `CLAUDE.md`,没有 `plugins/`,没有 `hooks/`,没有内存目录。 | | 工具链 | 在构建时写入 `/etc/cleanroom-*` 的 `node`/`npm` 版本,以便运行中的容器可以报告它是什么。 | 通过标签固定会违背初衷——`node:20-slim` 是一个移动的目标。摘要被捕获在 `FROM` 行中,并在 OCI 标签中重复出现。 ## `verify_clean_room.sh` 固定构建是不够的,因为容器启动时可以带有挂载(mounts)和 环境,从而重新引入镜像确切移除的内容。验证器被内置到 镜像中,并在**运行时**断言干净环境属性: ``` docker run --rm ghcr.io/kinohtago/cc-cleanroom:latest verify_clean_room.sh ``` 发生漂移的容器会大声报错,而不是产生一个看起来没问题的结果。 这是很容易被跳过的部分,也是使工件值得信赖的关键部分。 ## 身份验证 `setup-auth.sh` 执行一次交互式登录,并将结果持久化到一个命名的 Docker volume 中: ``` ./setup-auth.sh # login, store credentials in the auth volume ./setup-auth.sh --force # wipe and re-login (e.g. after token expiry) ``` **凭证被写入 volume,而不是镜像中。** 发布的镜像 不包含任何 token——你可以自己在镜像配置上验证这一点: ``` docker buildx imagetools inspect ghcr.io/kinohtago/cc-cleanroom:latest --raw ``` 后续运行会挂载该 volume: ``` docker run -it --rm -v claude-cleanroom-auth:/cleanroom/.config \ ghcr.io/kinohtago/cc-cleanroom:latest claude --version ``` ## 构建和发布 `.github/workflows/container-image-build.yml` 构建并推送到 GHCR。 | 触发器 | 生成的标签 | |---|---| | 推送到 `main` | `sha-`, `main` | | 推送标签 `v*` | ``, ``, `latest` | | `workflow_dispatch` | 你提供的 `extra_tag`(永远不会是 `latest`) | `latest` 仅在 `v*` 标签上移动,因此 `main` 可以随意变动,而不会改变其他人 拉取的内容。 多架构(`linux/amd64` + `linux/arm64`),并启用了**来源证明(provenance attestations)和 SBOM**—— 可复现工件的意义在于第三方可以对其进行审计,而这需要的不仅仅是一个摘要。 ### 关于工作流的 shell 处理的说明 每个 `${{ }}` 扩展都位于 action 的 `with:` 或 `env:` 块中。没有 内联到 `run:` 主体中;在 `run:` 块内,外部值作为 `$ENVVAR` 读取。 这是故意的——将 `${{ github.event.* }}` 内联到 shell 命令中是标准的 GitHub Actions 脚本注入向量,而在人们拉取的容器构建工作流中存在这种问题是极不妥的。 ## 重新固定 ``` docker buildx imagetools inspect node:20-slim # new index digest npm view @anthropic-ai/claude-code version # new CLI version ``` 更新 `FROM` 摘要和 `CLAUDE_CLI_VERSION`,然后在**新**标签下发布。保留 旧镜像:能够重新运行前一个镜像是进行固定的原因。 当前 CLI 的固定版本故意不是最新版本;Dockerfile 记录了原因。 ## 适用范围 - 在 macOS (Apple Silicon) 和 `linux/amd64` 上构建和使用。 - 该镜像隔离了*环境*。它不会使模型输出具有确定性—— 这里没有任何东西固定模型行为,也不应将其描述为能做到这一点。 - 不隶属于 Anthropic,也未得到其认可。 ## 许可证 MIT
标签:Claude Code, Cutter, Docker容器, Hakrawler, MITM代理, SOC Prime, 可复现性, 开发工具, 攻击面发现, 环境一致性, 环境隔离, 请求拦截, 验证脚本