diff --git a/.trivyignore b/.trivyignore index 5115dbe..98984b9 100644 --- a/.trivyignore +++ b/.trivyignore @@ -1,12 +1,13 @@ # Trivy CVE Suppressions — Upstream Dependencies -# Reviewed: 2026-02-12 | Milestone: M11-CIPipeline +# Reviewed: 2026-02-13 | Milestone: M11-CIPipeline # -# MITIGATED in this sprint: +# MITIGATED: # - Go stdlib CVEs (6): gosu rebuilt from source with Go 1.26 # - npm bundled CVEs (5): npm removed from production Node.js images +# - Node.js 20 → 24 LTS migration (#367): base images updated # -# REMAINING: OpenBao only (5 CVEs — 4 false positives + 1 upstream Go stdlib) -# Re-evaluate when upgrading openbao image beyond 2.5.0. +# REMAINING: OpenBao (5 CVEs) + Next.js bundled tar (3 CVEs) +# Re-evaluate when upgrading openbao image beyond 2.5.0 or Next.js beyond 16.1.6. # === OpenBao false positives === # Trivy reads Go module pseudo-version (v0.0.0-20260204...) from bin/bao @@ -16,6 +17,16 @@ CVE-2024-9180 # HIGH: privilege escalation (fixed in 2.0.3) CVE-2025-59043 # HIGH: DoS via malicious JSON (fixed in 2.4.1) CVE-2025-64761 # HIGH: identity group root escalation (fixed in 2.4.4) +# === Next.js bundled tar CVEs (upstream — waiting on Next.js release) === +# Next.js 16.1.6 bundles tar@7.5.2 in next/dist/compiled/tar/ (pre-compiled). +# This is NOT a pnpm dependency — it's embedded in the Next.js package itself. +# Affects web image only (orchestrator and API are clean). +# npm was also removed from all production images, eliminating the npm-bundled copy. +# To resolve: upgrade Next.js when a release bundles tar >= 7.5.7. +CVE-2026-23745 # HIGH: tar arbitrary file overwrite via unsanitized linkpaths (fixed in 7.5.3) +CVE-2026-23950 # HIGH: tar arbitrary file overwrite via Unicode path collision (fixed in 7.5.4) +CVE-2026-24842 # HIGH: tar arbitrary file creation via hardlink path traversal (needs tar >= 7.5.7) + # === OpenBao Go stdlib (waiting on upstream rebuild) === # OpenBao 2.5.0 compiled with Go 1.25.6, fix needs Go >= 1.25.7. # Cannot build OpenBao from source (large project). Waiting for upstream release. diff --git a/.woodpecker/api.yml b/.woodpecker/api.yml index ffb6628..90ef697 100644 --- a/.woodpecker/api.yml +++ b/.woodpecker/api.yml @@ -17,7 +17,7 @@ when: - ".woodpecker/api.yml" variables: - - &node_image "node:20-alpine" + - &node_image "node:24-alpine" - &install_deps | corepack enable pnpm install --frozen-lockfile diff --git a/.woodpecker/orchestrator.yml b/.woodpecker/orchestrator.yml index 6675d47..2d15af5 100644 --- a/.woodpecker/orchestrator.yml +++ b/.woodpecker/orchestrator.yml @@ -17,7 +17,7 @@ when: - ".woodpecker/orchestrator.yml" variables: - - &node_image "node:20-alpine" + - &node_image "node:24-alpine" - &install_deps | corepack enable pnpm install --frozen-lockfile diff --git a/.woodpecker/web.yml b/.woodpecker/web.yml index cda381e..d3f38a1 100644 --- a/.woodpecker/web.yml +++ b/.woodpecker/web.yml @@ -17,7 +17,7 @@ when: - ".woodpecker/web.yml" variables: - - &node_image "node:20-alpine" + - &node_image "node:24-alpine" - &install_deps | corepack enable pnpm install --frozen-lockfile diff --git a/apps/api/Dockerfile b/apps/api/Dockerfile index 1179f5c..6a6ce5a 100644 --- a/apps/api/Dockerfile +++ b/apps/api/Dockerfile @@ -2,7 +2,7 @@ # Enable BuildKit features for cache mounts # Base image for all stages -FROM node:20-alpine AS base +FROM node:24-alpine AS base # Install pnpm globally RUN corepack enable && corepack prepare pnpm@10.27.0 --activate @@ -53,10 +53,9 @@ RUN pnpm turbo build --filter=@mosaic/api --force # ====================== # Production stage # ====================== -FROM node:20-alpine AS production +FROM node:24-alpine AS production -# Remove npm (unused in production — we use pnpm) to eliminate bundled CVEs -# (cross-spawn CVE-2024-21538, glob CVE-2025-64756, tar CVE-2026-23745/23950/24842) +# Remove npm (unused in production — we use pnpm) to reduce attack surface RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx # Install dumb-init for proper signal handling diff --git a/apps/orchestrator/Dockerfile b/apps/orchestrator/Dockerfile index ccd9134..4909902 100644 --- a/apps/orchestrator/Dockerfile +++ b/apps/orchestrator/Dockerfile @@ -2,7 +2,7 @@ # Enable BuildKit features for cache mounts # Base image for all stages -FROM node:20-alpine AS base +FROM node:24-alpine AS base # Install pnpm globally RUN corepack enable && corepack prepare pnpm@10.27.0 --activate @@ -49,10 +49,15 @@ COPY --from=deps /app/apps/orchestrator/node_modules ./apps/orchestrator/node_mo # Build the orchestrator app using TurboRepo RUN pnpm turbo build --filter=@mosaic/orchestrator +# Remove compiled test/spec files from dist BEFORE copying to production. +# These contain test fixture secrets (fake AWS keys, RSA keys) that trigger Trivy. +# Must happen in builder stage so they never appear in any production image layer. +RUN find ./apps/orchestrator/dist \( -name '*.spec.js' -o -name '*.spec.js.map' -o -name '*.test.js' -o -name '*.test.js.map' \) -delete + # ====================== # Production stage # ====================== -FROM node:20-alpine AS production +FROM node:24-alpine AS production # Add metadata labels LABEL maintainer="mosaic-team@mosaicstack.dev" @@ -63,8 +68,7 @@ LABEL org.opencontainers.image.vendor="Mosaic Stack" LABEL org.opencontainers.image.title="Mosaic Orchestrator" LABEL org.opencontainers.image.description="Agent orchestration service for Mosaic Stack" -# Remove npm (unused in production — we use pnpm) to eliminate bundled CVEs -# (cross-spawn CVE-2024-21538, glob CVE-2025-64756, tar CVE-2026-23745/23950/24842) +# Remove npm (unused in production — we use pnpm) to reduce attack surface RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx # Install wget and dumb-init @@ -81,10 +85,8 @@ COPY --from=builder --chown=nestjs:nodejs /app/node_modules ./node_modules # Copy built packages (includes dist/ directories) COPY --from=builder --chown=nestjs:nodejs /app/packages ./packages -# Copy built orchestrator application +# Copy built orchestrator application (spec/test files already removed in builder stage) COPY --from=builder --chown=nestjs:nodejs /app/apps/orchestrator/dist ./apps/orchestrator/dist -# Remove compiled test files from production (contain test fixtures that trigger Trivy secret scanning) -RUN find ./apps/orchestrator/dist \( -name '*.spec.js' -o -name '*.spec.js.map' -o -name '*.test.js' -o -name '*.test.js.map' \) -print | xargs rm -f 2>/dev/null || true COPY --from=builder --chown=nestjs:nodejs /app/apps/orchestrator/package.json ./apps/orchestrator/ # Copy app's node_modules which contains symlinks to root node_modules diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile index e58f268..84a66e5 100644 --- a/apps/web/Dockerfile +++ b/apps/web/Dockerfile @@ -2,7 +2,7 @@ # Enable BuildKit features for cache mounts # Base image for all stages -FROM node:20-alpine AS base +FROM node:24-alpine AS base # Install pnpm globally RUN corepack enable && corepack prepare pnpm@10.27.0 --activate @@ -75,10 +75,9 @@ RUN mkdir -p ./apps/web/public # ====================== # Production stage # ====================== -FROM node:20-alpine AS production +FROM node:24-alpine AS production -# Remove npm (unused in production — we use pnpm) to eliminate bundled CVEs -# (cross-spawn CVE-2024-21538, glob CVE-2025-64756, tar CVE-2026-23745/23950/24842) +# Remove npm (unused in production — we use pnpm) to reduce attack surface RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx # Install pnpm (needed for pnpm start command) diff --git a/docs/tasks.md b/docs/tasks.md index cc510d0..036bde0 100644 --- a/docs/tasks.md +++ b/docs/tasks.md @@ -71,6 +71,6 @@ | id | status | description | issue | repo | branch | depends_on | blocks | agent | started_at | completed_at | estimate | used | | ----------- | ------ | -------------------------------------------------------------------------------------------- | ----- | ------------ | ---------- | ----------------------- | ----------- | ----- | ----------------- | ----------------- | -------- | ---- | | CI-FIX6-001 | done | Add @mosaic/ui build to web.yml build-shared step (fixes 10 test suites + 20 typecheck errs) | | ci | fix/ci-366 | | CI-FIX6-003 | w-14 | 2026-02-12T21:00Z | 2026-02-12T21:01Z | 3K | 3K | -| CI-FIX6-002 | done | Fix Dockerfile find -o parentheses bug (fixes 5 Trivy false positives in spec files) | | orchestrator | fix/ci-366 | | CI-FIX6-004 | w-15 | 2026-02-12T21:00Z | 2026-02-12T21:01Z | 3K | 3K | +| CI-FIX6-002 | done | Move spec file removal to builder stage (layer-aware); add tar CVEs to .trivyignore | | orchestrator | fix/ci-366 | | CI-FIX6-004 | w-15 | 2026-02-12T21:00Z | 2026-02-12T21:15Z | 3K | 5K | | CI-FIX6-003 | done | Add React.ChangeEvent types to ~10 web files with untyped event handlers (49 lint + 19 TS) | | web | fix/ci-366 | CI-FIX6-001 | CI-FIX6-004 | w-16 | 2026-02-12T21:02Z | 2026-02-12T21:08Z | 12K | 8K | | CI-FIX6-004 | done | Verification: pnpm lint && pnpm typecheck && pnpm test on web; Dockerfile find validation | | all | fix/ci-366 | CI-FIX6-002,CI-FIX6-003 | | orch | 2026-02-12T21:08Z | 2026-02-12T21:10Z | 5K | 2K | diff --git a/package.json b/package.json index 5f14630..7725f4b 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "packageManager": "pnpm@10.19.0", "engines": { - "node": ">=20.0.0" + "node": ">=24.0.0" }, "scripts": { "build": "turbo run build",