diff --git a/.trivyignore b/.trivyignore index e4bbe2c..5799180 100644 --- a/.trivyignore +++ b/.trivyignore @@ -11,9 +11,13 @@ # are pinned by digest. The weekly update-base-images.yml workflow rotates digests # automatically, pulling in security patches as soon as Google publishes them. # -# npm dependency status (last verified: 2026-03-28): +# npm dependency status (last verified: 2026-07-10): # npm audit --omit=dev reports 0 vulnerabilities. -# Resolved in this pass (all were MODERATE, none HIGH/CRITICAL): +# Resolved in this pass: +# - protobufjs@7.5.9 (CVE-2026-48712 HIGH) → patched via overrides bump to 7.6.1 +# - ws@8.20.1 (CVE-2026-48779 HIGH) → patched via overrides to >=8.21.0 +# - libssl3 (CVE-2026-45447 HIGH) → patched via Dockerfile security-patches stage (3.0.20-1~deb12u2) +# Previously resolved (MODERATE, no entry needed): # - fastify@<=5.8.2 (GHSA-444r-cwp2-x5xf) → patched by upgrade to 5.8.3+ # - brace-expansion@4.0.0-5.0.4 (GHSA-f886-m6hf-6m8v) → patched via lockfile # - yaml@2.0.0-2.8.2 (GHSA-48c2-rrv3-qjmp) → patched via lockfile @@ -30,34 +34,22 @@ # Every entry MUST include: CVE ID, date added, package, reason, and review trigger. # --------------------------------------------------------------------------- -# CVE-2026-28390 -# Added: 2026-04-10 -# Package: libssl3 (debian 12.13) in gcr.io/distroless/nodejs24-debian12:nonroot -# Fixed: 3.0.19-1~deb12u2 (available in Debian repos; NOT yet in distroless image) +# CVE-2026-45447 (libssl3), CVE-2026-48712 (protobufjs), CVE-2026-48779 (ws) # -# Assessment: -# The vulnerability is a NULL-pointer dereference in OpenSSL's CMS -# (Cryptographic Message Syntax) implementation, triggerable only when the -# CMS code path is invoked with a crafted message. Standard HTTPS / TLS -# connections do NOT traverse the CMS code path; it is relevant only for -# S/MIME, code-signing, and PKCS#7 workflows — none of which this API uses. -# Attack surface is low for a web API that terminates TLS without processing -# CMS payloads. +# All three HIGH vulnerabilities from the 2026-07-10 Trivy scan are fixed +# directly in code — no .trivyignore suppression required: # -# Dockerfile fix included (belt-and-suspenders): -# Stages 2.5a / 2.5b in Dockerfile overlay the patched libssl3 .so files and -# patch the distroless dpkg metadata so Trivy should report 3.0.19 after the -# next build. This .trivyignore entry acts as a safety net in the unlikely -# event that the dpkg metadata path in the distroless image differs from the -# expected /var/lib/dpkg layout. +# CVE-2026-45447 — libssl3 Heap Use-After-Free in PKCS7_verify() +# Fixed by: Dockerfile security-patches stage installs 3.0.20-1~deb12u2 +# and overlays patched .so files + dpkg metadata into production image. +# Remove Dockerfile stages 2.5a / 2.5b once the distroless digest is rotated +# to bundle libssl3 >= 3.0.20-1~deb12u2 natively. # -# Review trigger: -# Remove this entry AND the Dockerfile stages 2.5a / 2.5b once -# update-base-images.yml rotates the distroless digest to a version that -# bundles libssl3 >= 3.0.19-1~deb12u2 natively. -CVE-2026-28390 - -# Remove the entry immediately when the fixed version has been deployed. +# CVE-2026-48712 — protobufjs DoS via uncontrolled recursion +# Fixed by: package.json overrides bump from 7.5.9 → 7.6.1. +# +# CVE-2026-48779 — ws DoS via memory exhaustion from small WebSocket fragments +# Fixed by: package.json overrides "ws": ">=8.21.0" (pulled by @supabase/realtime-js). # ─── NOTE ──────────────────────────────────────────────────────────────────── # CVE-2026-0861 (libc6 / glibc memalign integer overflow) was previously listed diff --git a/Dockerfile b/Dockerfile index ce408aa..88308a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,7 +58,7 @@ RUN npm ci --omit=dev \ FROM gcr.io/distroless/nodejs24-debian12:nonroot@sha256:6c75c6e4771c2ea5f02aaf991abdc77391acd3a580accd9d7b68651f12c60dc0 AS distroless-meta # ---- Stage 2.5b: Security patches ----------------------------------------- -# CVE-2026-28390: libssl3 NULL-ptr deref in CMS; DoS; fixed in 3.0.19-1~deb12u2. +# CVE-2026-45447: libssl3 Heap Use-After-Free in OpenSSL PKCS7_verify(); fixed in 3.0.20-1~deb12u2. # The pinned distroless digest (sha256:6c75c6e...) was published before that fix # landed in the upstream image. This stage: # (a) installs the patched libssl3 / libcrypto shared libraries, and @@ -68,11 +68,11 @@ FROM gcr.io/distroless/nodejs24-debian12:nonroot@sha256:6c75c6e4771c2ea5f02aaf99 # # Remove this stage (and the matching .trivyignore entry) once # update-base-images.yml rotates the distroless digest to a version that -# bundles libssl3 >= 3.0.19-1~deb12u2. +# bundles libssl3 >= 3.0.20-1~deb12u2. FROM node:24.2.0-bookworm-slim@sha256:1a6a7b2e2e2c80a6973f57aa8b0c6ad67a961ddbc5ef326c448e133f93564ff9 AS security-patches RUN apt-get update \ - && apt-get install -y --no-install-recommends "libssl3=3.0.19-1~deb12u2" \ + && apt-get install -y --no-install-recommends "libssl3=3.0.20-1~deb12u2" \ && rm -rf /var/lib/apt/lists/* # Carry the distroless dpkg metadata into this shell-capable stage so the @@ -84,8 +84,8 @@ COPY --from=distroless-meta /var/lib/dpkg /tmp/distroless-dpkg/ # The || true prevents a build failure when the distroless image ships a future # version where this version string no longer appears. RUN find /tmp/distroless-dpkg -type f \ - | xargs grep -l "3\.0\.18-1~deb12u2" 2>/dev/null \ - | xargs sed -i 's/3\.0\.18-1~deb12u2/3.0.19-1~deb12u2/g' \ + | xargs grep -l "3\.0\.19-1~deb12u2" 2>/dev/null \ + | xargs sed -i 's/3\.0\.19-1~deb12u2/3.0.20-1~deb12u2/g' \ || true # ---- Stage 3: Production (distroless) ------------------------------------- @@ -116,11 +116,11 @@ COPY --from=builder /workspace/dist ./dist # Healthcheck script — uses Node built-in http (curl not available in distroless). COPY healthcheck.js ./healthcheck.js -# Overlay patched libssl3 (CVE-2026-28390 — fixed in 3.0.19-1~deb12u2). +# Overlay patched libssl3 (CVE-2026-45447 — fixed in 3.0.20-1~deb12u2). # Replaces the vulnerable shared libraries bundled in the distroless base and # overlays the patched dpkg metadata so Trivy reports the corrected version. # Remove these three COPY lines (and stages 2.5a / 2.5b) once the distroless -# digest is rotated to include libssl3 >= 3.0.19-1~deb12u2. +# digest is rotated to include libssl3 >= 3.0.20-1~deb12u2. COPY --from=security-patches /usr/lib/x86_64-linux-gnu/libssl.so.3 /usr/lib/x86_64-linux-gnu/libssl.so.3 COPY --from=security-patches /usr/lib/x86_64-linux-gnu/libcrypto.so.3 /usr/lib/x86_64-linux-gnu/libcrypto.so.3 COPY --from=security-patches /tmp/distroless-dpkg/ /var/lib/dpkg/ diff --git a/package-lock.json b/package-lock.json index 7dc4f86..6c7c8b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2663,9 +2663,9 @@ "license": "BSD-3-Clause" }, "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/fetch": { @@ -6632,16 +6632,16 @@ } }, "node_modules/protobufjs": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.9.tgz", - "integrity": "sha512-Od4muIm3HW1AouyHF5lONOf1FWo3hY1NbFDoy191X9GzhpgW1clCoaFjfVs2rKJNFYpTNJbje4cbAIDBZJ63ZA==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.1.tgz", + "integrity": "sha512-4K0myLaWL5EteuSAro91EGFgcfVgxb64Jx+7oDAY6GOkXD4M69yuSEljNcInGVCA5sOPxmZ/EqDLj2x0Q0+Ygg==", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", - "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.2", @@ -6649,7 +6649,7 @@ "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", - "long": "^5.0.0" + "long": "^5.3.2" }, "engines": { "node": ">=12.0.0" @@ -7641,9 +7641,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.20.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", - "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "license": "MIT", "engines": { "node": ">=10.0.0" diff --git a/package.json b/package.json index 6f2a499..e1608dc 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,8 @@ "@rollup/rollup-linux-x64-gnu": "^4.0.0" }, "overrides": { - "protobufjs": "7.5.9", - "fast-uri": "3.1.2" + "protobufjs": "7.6.1", + "fast-uri": "3.1.2", + "ws": ">=8.21.0" } }