Repository navigation
ci: protect the Playwright config and pin images by digest - #146
Conversation
There was a problem hiding this comment.
If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.
Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 48 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request pins Docker base and service images by digest across multiple Dockerfiles and docker-compose.yml, documents the image pinning policy in AGENTS.md, and extends the protected paths list to include Playwright configuration and global setup/teardown files. The review feedback suggests broadening the regex matching global setup/teardown files to cover common naming variations (such as camelCase, snake_case, and directory structures) to prevent potential security bypasses, along with adding corresponding test cases.
| // The Playwright config and global setup decide which e2e tests run (`testIgnore`, `grep`, a setup that exits | ||
| // early), so they count as test runner config in any directory. | ||
| [/(^|\/)playwright(\.[a-z]+)?\.config\.[cm]?[jt]s$/, 'test runner config'], | ||
| [/(^|\/)global-(setup|teardown)\.[cm]?[jt]s$/, 'test runner global setup'], |
There was a problem hiding this comment.
The current regex /(^|\/)global-(setup|teardown)\.[cm]?[jt]s$/ only matches global setup/teardown files that use a hyphen (e.g., global-setup.ts). It will miss files using camelCase (e.g., globalSetup.ts), snake_case (e.g., global_setup.ts), or structured directories (e.g., global-setup/index.ts). Update the regex to match these common naming conventions and directory structures to prevent potential bypasses of the protected path gate.
| [/(^|\/)global-(setup|teardown)\.[cm]?[jt]s$/, 'test runner global setup'], | |
| [/(^|\/)global[-_]?(setup|teardown|Setup|Teardown)(\.[cm]?[jt]s$|\/)/, 'test runner global setup'], |
| 'e2e/global-setup.ts', | ||
| 'e2e/global-teardown.mjs', |
There was a problem hiding this comment.
Add test cases for the camelCase, snake_case, and directory-based global setup/teardown variations to ensure they are correctly flagged as protected paths.
| 'e2e/global-setup.ts', | |
| 'e2e/global-teardown.mjs', | |
| 'e2e/global-setup.ts', | |
| 'e2e/global-teardown.mjs', | |
| 'e2e/globalSetup.ts', | |
| 'e2e/global_teardown.mjs', | |
| 'e2e/global-setup/index.ts', | |
| 'e2e/global-teardown/helper.js', |
- protected-paths: playwright*.config.* and global-setup/teardown files in any directory count as test runner config, so a PR cannot quietly turn off the e2e gate. Tests and the protected list in AGENTS.md and the plan are updated. - Pin every container image by digest (image:tag@sha256:<index digest>): docker-compose.yml (postgres, gotrue, mailpit), the Dockerfile base images, and the postgres service in ci.yml and protected.yml. node:26-slim is pinned to the Node 26.11.1 build because the current 26.12.0 build is younger than the one-day release age. - AGENTS.md: "Updating pinned images" explains how to bump a pin. - Workflows cancel in-progress runs only for pull requests, so pushes to main always get a result. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
c89b42e to
199ad6f
Compare
Summary
Two follow-ups from the security review of #91.
Playwright config is a protected path.
tools/ci/protected-paths.mjsnow matchesplaywright*.config.{js,ts,mjs,cjs,mts,cts}andglobal-setup.*/global-teardown.*in any directory as test runner config. A PR can no longer turn off the e2e gate (testIgnore,grep, a global setup that exits early) without the protected-path review.tools/test/protected-paths.test.tscovers both rules, plus e2e specs and helpers that stay ordinary. The protected list inAGENTS.mdand plan §G6 is updated.Images pinned by digest as
image:tag@sha256:<multi-arch index digest>:docker-compose.yml:postgres:17,supabase/gotrue:v2.197.0,axllent/mailpit:v1.31.5Dockerfileandapps/extract/Dockerfile:node:26-slim;apps/web/Dockerfile:node:22-alpineci.ymlandprotected.yml: thepostgres:17service (MinIO was already pinned)No tag was bumped.
node:26-slimnow points to Node 26.12.0, pushed 2026-10-14T20:41Z, which is less than the one-day release age. The pin is the previous26-slimbuild (Node 26.11.1, pushed 2026-10-08, still reachable as26.11.1-slim). Every other digest is the current build of its tag, and all of them are at least 4 days old.AGENTS.mdnow has an "Updating pinned images" section. The repo has no Renovate or Dependabot config yet; both updatetag@digestpins when one is added.Concurrency:
ci,gitleaks,docs-checkandprotectedsetcancel-in-progress: ${{ github.event_name == 'pull_request' }}, so a push tomainalways finishes. The last two run only onpull_request, so they behave as before.e2e.ymlande2e/come from #91 and are not onmainyet. Whichever of #91 and this PR merges second should pin the e2e workflow's images and use the same concurrency setting there. The new rules already covere2e/playwright.config.tsande2e/global-setup.ts.This PR edits
tools/ci/and the workflows, so it runs its own editedprotectedworkflow. No check is removed or loosened: the only workflow changes are digest pins and the concurrency expression.Test plan
docker compose config --imagesresolves the pinned referencesdocker compose pull db auth mailpitpulls the pinned digests;node:26-slim@...andnode:22-alpine@...pull, and the node 26 pin reportsv26.11.1pnpm -s lint,pnpm -s typecheckpnpm exec vitest run tools/test(8 tests pass)pnpm docs:checkCloses #127
🤖 Generated with Claude Code
📌 TL;DR
This PR hardens the CI/CD pipeline by pinning all container images to specific SHA256 digests to prevent supply-chain attacks and ensuring critical workflows (like
mainbranch builds) are not cancelled by concurrent runs. It also expands the "protected paths" security gate to include Playwright configuration files, ensuring e2e test runners cannot be silently modified without review.🎯 Type of Change
🔍 Changes Walkthrough
.github/workflows/*.ymlcancel-in-progressto only cancel onpull_requestevents (preventing cancellation ofmain/pushruns). Pinnedpostgres:17service image to a specific digest.AGENTS.mdDockerfilenode:26-slimbase images to a specific SHA256 digest.apps/extract/Dockerfilenode:26-slimbase images to a specific SHA256 digest.apps/web/Dockerfilenode:22-alpinebase images to a specific SHA256 digest.docker-compose.ymlpostgres:17,supabase/gotrue, andaxllent/mailpitimages to specific SHA256 digests.docs/plan/crove-os-kernel.mdtools/ci/protected-paths.mjsplaywright*.config.*andglobal-setup/teardown.*files from unauthorized changes.tools/test/protected-paths.test.ts📊 Architectural Flow
flowchart TD subgraph "Supply Chain Security" A[Container Images] -->|Pinned to SHA256 Digest| B[Docker / CI Runtime] B -->|Immutable Build| C[Production / CI Environment] end subgraph "CI Concurrency Control" D[GitHub Event] --> E{Event Type?} E -->|pull_request| F[Cancel In-Progress: True] E -->|push / workflow_dispatch| G[Cancel In-Progress: False] end subgraph "Protected Paths Gate (G6)" H[PR Diff] --> I[tools/ci/protected-paths.mjs] I -->|Matches Regex| J[Playwright Configs / Global Setup] I -->|Matches Regex| K[Vitest / Package.json / etc.] J --> L[Flag as Protected] K --> L L --> M[Require Security Review / Invariant Suite] end