Skip to content

chore: harden webapp docker image#3845

Merged
nicktrn merged 5 commits into
mainfrom
chore/harden-webapp-image
Jun 5, 2026
Merged

chore: harden webapp docker image#3845
nicktrn merged 5 commits into
mainfrom
chore/harden-webapp-image

Conversation

@nicktrn
Copy link
Copy Markdown
Collaborator

@nicktrn nicktrn commented Jun 5, 2026

Hardens the webapp Docker image and adds a CVE scan of each published image.

  • Base image bullseye-slimbookworm-slim (Debian 12), pinned by digest. Adds apt-get upgrade + --no-install-recommends + apt-cache cleanup across the build stages so OS packages are patched at build time.
  • Moves the react-email CLI to devDependencies in internal-packages/emails — only the email dev preview script uses it; the runtime render path is @react-email/render + @react-email/components. This also drops the bundled esbuild binary from the production image.
  • Bumps goose v3.26.0 → v3.27.1 and its Go builder image 1.23 → 1.26.
  • Adds a reusable Trivy image-scan workflow wired into publish.yml, so every published image (main builds and releases) is scanned for OS-package CVEs right after it's pushed to GHCR. Report-only (writes to the run summary), runs alongside the worker publishes so it never blocks a deploy.

Verified locally: the image builds clean on the new base, and @react-email/render carries no esbuild dependency so email rendering is unaffected.

@nicktrn nicktrn self-assigned this Jun 5, 2026
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 5, 2026

⚠️ No Changeset found

Latest commit: 93199f2

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 5, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 09af7511-142e-42d4-a257-f652ab05ef3e

📥 Commits

Reviewing files that changed from the base of the PR and between 64011aa and 93199f2.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • .github/workflows/publish-webapp.yml
  • .github/workflows/publish.yml
  • .github/workflows/trivy-image-webapp.yml
  • docker/Dockerfile
  • internal-packages/emails/package.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • .github/workflows/publish.yml
  • internal-packages/emails/package.json
  • docker/Dockerfile
  • .github/workflows/trivy-image-webapp.yml
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (33)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: audit
  • GitHub Check: audit
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (actions)
  • GitHub Check: Build and publish previews
🔇 Additional comments (1)
.github/workflows/publish-webapp.yml (1)

17-23: LGTM!


Walkthrough

This PR adds container image vulnerability scanning to the CI/CD pipeline and hardens the Docker build configuration. The main feature adds a Trivy-based scanning workflow that inspects published webapp images for OS-level CVEs after each successful release, reporting HIGH and CRITICAL severity findings to the GitHub step summary. Supporting changes update Node.js and Go toolchain versions in the Dockerfile, apply security hardening practices to container image layers, and reclassify react-email as a development-only dependency.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: hardening the webapp Docker image, which is the primary objective reflected in all file modifications.
Description check ✅ Passed The description comprehensively covers all major changes, testing verification, and technical rationale. However, the PR template sections (Closes #issue, Checklist, Testing, Changelog, Screenshots) are not followed.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/harden-webapp-image

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
docker/Dockerfile (1)

46-46: 💤 Low value

Consider installing only the additional package needed.

The builder stage extends base, which already installs openssl and dumb-init. Since ca-certificates is the only new dependency here, you could reduce redundancy:

♻️ Optional simplification
-RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends openssl dumb-init ca-certificates && rm -rf /var/lib/apt/lists/*
+RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends ca-certificates && rm -rf /var/lib/apt/lists/*

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6f71783e-17c0-4a71-8a79-6ed0c07a0c0a

📥 Commits

Reviewing files that changed from the base of the PR and between 1466a15 and 892b056.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • .github/workflows/publish-webapp.yml
  • .github/workflows/publish.yml
  • .github/workflows/trivy-image-webapp.yml
  • docker/Dockerfile
  • internal-packages/emails/package.json
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (32)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp
  • GitHub Check: audit
  • GitHub Check: audit
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Build and publish previews
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,ts,tsx,jsx,css,json,md}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier for code formatting and run pnpm run format before committing

Files:

  • internal-packages/emails/package.json
🧠 Learnings (10)
📚 Learning: 2026-05-12T14:13:17.114Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3561
File: .claude/scripts/check-review-md.sh:76-79
Timestamp: 2026-05-12T14:13:17.114Z
Learning: In the triggerdotdev/trigger.dev repository, `.claude/REVIEW.md` drift/audit checking is handled by an LLM-based workflow using `anthropics/claude-code-action` (mirroring `.github/workflows/claude-md-audit.yml`), not a static bash script. The LLM audit catches semantic drift, stale references, contradictions, and missing/obsolete rules — not just deleted paths. The bash script `.claude/scripts/check-review-md.sh` was dropped in favor of this approach.

Applied to files:

  • .github/workflows/trivy-image-webapp.yml
📚 Learning: 2026-03-22T19:26:49.299Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3187
File: internal-packages/emails/emails/alert-error-group.tsx:58-58
Timestamp: 2026-03-22T19:26:49.299Z
Learning: In the triggerdotdev/trigger.dev codebase, email template files under `internal-packages/emails/emails/` must use `export default function Email(...)` (default export) because the React Email previewer requires a default export to discover and render templates. Do not flag default exports in these files as violations of the "use named exports" coding guideline.

Applied to files:

  • internal-packages/emails/package.json
📚 Learning: 2026-04-27T16:46:05.550Z
Learnt from: nicktrn
Repo: triggerdotdev/trigger.dev PR: 3456
File: apps/webapp/package.json:152-152
Timestamp: 2026-04-27T16:46:05.550Z
Learning: In `apps/webapp`, the `effect` npm package is an intentional runtime dependency used in `apps/webapp/app/utils/updateMetadata.server.ts` (and related modules) for Schedule + Fiber-based metadata update logic. Specifically, the four Effect API usages are: `Duration.divide`, `STM.cond`, namespace exports for `Effect`/`Schedule`/`Duration`/`Fiber`, and the `Fiber.RuntimeFiber` type. Do not flag `effect` as an unused or misplaced dependency in `apps/webapp/package.json`.

Applied to files:

  • internal-packages/emails/package.json
📚 Learning: 2026-03-02T12:43:34.140Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: packages/cli-v3/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:34.140Z
Learning: Applies to packages/cli-v3/src/deploy/buildImage.ts : Build Docker images using `src/deploy/buildImage.ts` for local Docker/Depot or remote builds

Applied to files:

  • docker/Dockerfile
📚 Learning: 2026-06-02T21:20:43.541Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-06-02T21:20:43.541Z
Learning: Applies to **/Dockerfile{,.prod}{,.dev}* **/docker-compose*.{yml,yaml} **/**.Dockerfile : Always use multiplatform/index digests when updating Docker image references, never use architecture-specific digests

Applied to files:

  • docker/Dockerfile
📚 Learning: 2025-02-10T10:54:17.345Z
Learnt from: zvictor
Repo: triggerdotdev/trigger.dev PR: 1686
File: packages/build/src/extensions/python.ts:85-87
Timestamp: 2025-02-10T10:54:17.345Z
Learning: In Python-related Dockerfiles for trigger.dev, avoid adding explicit Python version pinning as the base image already provides conservative version management. Additional pinning would unnecessarily slow down builds.

Applied to files:

  • docker/Dockerfile
📚 Learning: 2026-03-02T12:43:34.140Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: packages/cli-v3/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:34.140Z
Learning: Applies to packages/cli-v3/src/build/**/* : Bundle worker code using the build system in `src/build/` based on configuration from `trigger.config.ts`

Applied to files:

  • docker/Dockerfile
📚 Learning: 2026-04-16T14:19:16.330Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: apps/webapp/CLAUDE.md:0-0
Timestamp: 2026-04-16T14:19:16.330Z
Learning: Never run `pnpm run build --filter webapp` to verify changes. Use typecheck from the repo root instead (`pnpm run typecheck --filter webapp`). Building proves almost nothing about correctness; only run typecheck after major changes (new files, significant refactors, schema changes)

Applied to files:

  • docker/Dockerfile
📚 Learning: 2026-03-02T12:43:34.140Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: packages/cli-v3/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:34.140Z
Learning: Applies to packages/cli-v3/src/build/**/* : Build system in `src/build/` should use configuration from `trigger.config.ts` in user projects to determine bundling, build extensions, and output structure

Applied to files:

  • docker/Dockerfile
📚 Learning: 2025-10-08T11:48:12.327Z
Learnt from: nicktrn
Repo: triggerdotdev/trigger.dev PR: 2593
File: packages/core/src/v3/workers/warmStartClient.ts:168-170
Timestamp: 2025-10-08T11:48:12.327Z
Learning: The trigger.dev runners execute only in Node 21 and 22 environments, so modern Node.js APIs like AbortSignal.any (introduced in v20.3.0) are supported.

Applied to files:

  • docker/Dockerfile
🔇 Additional comments (8)
internal-packages/emails/package.json (1)

26-27: Approve: moving react-email to devDependencies is safe

internal-packages/emails/src contains no from 'react-email' or require('react-email') usages, so production shouldn’t break. Runtime email rendering still relies on @react-email/render and @react-email/components in dependencies, while email dev continues to use the CLI from the dev dependency.

.github/workflows/publish-webapp.yml (1)

17-23: LGTM!

.github/workflows/trivy-image-webapp.yml (1)

1-66: LGTM!

.github/workflows/publish.yml (1)

100-109: LGTM!

docker/Dockerfile (4)

16-16: LGTM!


78-78: LGTM!


3-4: Confirm golang:1.26-alpine and pressly/goose@v3.27.1 are available

  • golang:1.26-alpine exists on Docker Hub.
  • pressly/goose release v3.27.1 exists, so the version bump in the builder stage is valid.

1-1: Verify this is a multiplatform digest.

The digest should be a manifest-list/index digest rather than an architecture-specific one to support the multiplatform build (linux/amd64,linux/arm64) in the publish workflow.

#!/bin/bash
# Verify the digest is a multiplatform manifest list
docker manifest inspect node:20.20.2-bookworm-slim@sha256:2cf067cfed83d5ea958367df9f966191a942351a2df77d6f0193e162b5febfc0 2>/dev/null | jq -r '.mediaType // "single-arch"'
# Expected: application/vnd.oci.image.index.v1+json or application/vnd.docker.distribution.manifest.list.v2+json

Based on learnings: "Always use multiplatform/index digests when updating Docker image references, never use architecture-specific digests"

@nicktrn nicktrn force-pushed the chore/harden-webapp-image branch from 64011aa to 93199f2 Compare June 5, 2026 15:01
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jun 5, 2026

Open in StackBlitz

@trigger.dev/build

npm i https://pkg.pr.new/@trigger.dev/build@93199f2

trigger.dev

npm i https://pkg.pr.new/trigger.dev@93199f2

@trigger.dev/core

npm i https://pkg.pr.new/@trigger.dev/core@93199f2

@trigger.dev/plugins

npm i https://pkg.pr.new/@trigger.dev/plugins@93199f2

@trigger.dev/python

npm i https://pkg.pr.new/@trigger.dev/python@93199f2

@trigger.dev/react-hooks

npm i https://pkg.pr.new/@trigger.dev/react-hooks@93199f2

@trigger.dev/redis-worker

npm i https://pkg.pr.new/@trigger.dev/redis-worker@93199f2

@trigger.dev/rsc

npm i https://pkg.pr.new/@trigger.dev/rsc@93199f2

@trigger.dev/schema-to-json

npm i https://pkg.pr.new/@trigger.dev/schema-to-json@93199f2

@trigger.dev/sdk

npm i https://pkg.pr.new/@trigger.dev/sdk@93199f2

commit: 93199f2

@nicktrn nicktrn merged commit 16d59aa into main Jun 5, 2026
48 checks passed
@nicktrn nicktrn deleted the chore/harden-webapp-image branch June 5, 2026 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants