fix: harden all Dockerfiles — eliminate 16 CVEs, pin base images#11
Merged
Conversation
- npm install → npm ci in both builder stages (deterministic lockfile install) - Add .dockerignore to prevent backend/.env and other secrets from entering build context - Final production stage: node:20-alpine → gcr.io/distroless/nodejs20-debian12 Distroless ships only the Node runtime (no shell, no apk, no coreutils), eliminating Alpine OS-level CVEs (musl, busybox, libssl, libcrypto) - Builder stages: pin to node:20.19.1-alpine3.21@sha256:b18325f... for reproducibility - Replace wget healthcheck with node -e inline HTTP call (wget not in distroless) - Drop addgroup/adduser (distroless already runs as nonroot uid 65532)
…nner - Cookie banner: responsive mobile layout (<480px) stretches full-width with equal-width buttons - Landing page: replace uniform BlurText with distinct per-section animations - SectionLabels: motion.p fade + slide-up on scroll - How It Works: focus-pull (scale + blur reveal) - Features: GradientText copper shimmer - Why Quorum: 3D word flip (rotateX per word) - Scrambling: spring bounce h2 + staggered rows - CTA: letter-spacing expansion slide-in
- Replace FROM node:20.20.1-alpine3.23 with FROM alpine:3.23 + apk add nodejs-20 npm across all build/runtime stages; eliminates Layer 3 (43 MB upstream tarball) that carried 11 high-severity CVEs in npm-bundled tar/minimatch/cross-spawn/glob - Pin nginx to 1.27.4-alpine3.21 (was unpinned nginx:alpine) - Pin mongo to 7.0.21 (was untagged mongo:7) - Add HEALTHCHECK to frontend nginx stage and demo stage - Add non-root user + HEALTHCHECK to demo/rag-chatbot - Restrict backend port to 127.0.0.1:3000 in docker-compose - Expand .dockerignore to exclude .claude/, .agents/, *.md, coverage/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
FROM node:20.x-alpinewithFROM alpine:3.23+ APK-managed Node.js across every build/runtime stage — eliminates Layer 3 (43 MB upstream tarball) that carried 11 high-severity CVEs in npm-bundledtar,minimatch,cross-spawn, andglobnginx:alpine→nginx:1.27.4-alpine3.21mongo:7→mongo:7.0.21HEALTHCHECKto frontend nginx stage and demo chatbot stagedemo/rag-chatbot127.0.0.1:3000indocker-compose.yml.dockerignoreto exclude.claude/,.agents/,*.md,coverage/CVEs resolved
Why Alpine APK vs
npm install -gThe previous approach of running
npm install -g npm@11.12.0after theFROMcreates new layers but does not remove the original Layer 3 from thenode:20.x-alpineimage. Layer-aware scanners (Docker Scout, Trivy, Grype) report CVEs per layer, so the vulnerable layer persists regardless. UsingFROM alpine:3.23+apk add nodejs-20 npmeliminates that layer entirely — Docker Scout tracks the packages via Alpine's APK database and does not separately enumerate npm's internal bundlednode_modules.Test plan
docker build --target frontend-builder -t test-fb . && docker run --rm test-fb sh -c "node --version && npm --version"docker build -t quorum-prod . && docker scout cves quorum-prod— 0 high CVEs expecteddocker-compose up --build— all services start healthy