Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 50 additions & 11 deletions apps/backend/Dockerfile.worker
Original file line number Diff line number Diff line change
Expand Up @@ -239,20 +239,24 @@ RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& rm -rf /var/lib/apt/lists/* \
&& npm install -g "npm@${NPM_VERSION}" \
# CVE-2026-14257 (HIGH, brace-expansion ReDoS): npm 11.18.0 bundles
# brace-expansion 5.0.7 under its OWN node_modules. npm is a BUILD-time tool
# (it installed cdxgen above); the celery worker never invokes it at runtime,
# so this is not runtime-reachable — but 5.0.8 is a drop-in patch, so we
# REPLACE the vulnerable copy rather than blanket-ignore the CVE ID (an
# ignore would also mask brace-expansion findings elsewhere). Verbatim
# npm-pack swap, same pattern as the cdxgen tar override below.
&& npm pack [email protected] --pack-destination /tmp \
# brace-expansion ReDoS/OOM chain under npm's OWN node_modules. npm ships
# 5.0.7 (CVE-2026-14257); 5.0.8 fixed that but is itself vulnerable to
# CVE-2026-69152, whose fix landed in 5.0.9. npm is a BUILD-time tool here
# (it installed cdxgen above) and the celery worker never invokes it at
# runtime, so neither is runtime-reachable — we still REPLACE rather than
# blanket-ignore, because an ignore would mask the same CVE ids on copies
# that ARE reachable (cdxgen's tree, overridden below).
#
# Pinning a fixed version is not a one-time act: this line said 5.0.8 until
# 5.0.8 became the vulnerable one. Re-check it whenever the image scan
# flags brace-expansion again.
&& npm pack [email protected] --pack-destination /tmp \
&& rm -rf /usr/lib/node_modules/npm/node_modules/brace-expansion \
&& mkdir -p /usr/lib/node_modules/npm/node_modules/brace-expansion \
&& tar -xzf /tmp/brace-expansion-5.0.8.tgz --strip-components=1 \
&& tar -xzf /tmp/brace-expansion-5.0.9.tgz --strip-components=1 \
-C /usr/lib/node_modules/npm/node_modules/brace-expansion \
&& rm -f /tmp/brace-expansion-5.0.8.tgz \
&& node -e "const p=require('/usr/lib/node_modules/npm/node_modules/brace-expansion/package.json');if(p.version!=='5.0.8'){throw new Error('brace-expansion override failed: '+p.version)}" \
&& rm -f /tmp/brace-expansion-5.0.9.tgz \
&& node -e "const p=require('/usr/lib/node_modules/npm/node_modules/brace-expansion/package.json');if(p.version!=='5.0.9'){throw new Error('brace-expansion override failed: '+p.version)}" \
&& node --version \
&& npm --version

Expand Down Expand Up @@ -328,6 +332,41 @@ RUN npm install -g --omit=dev --omit=optional "@cyclonedx/cdxgen@${CDXGEN_VERSIO
-C /usr/lib/node_modules/@cyclonedx/cdxgen/node_modules/tar \
&& rm -f /tmp/tar-7.5.19.tgz \
&& node -e "const p=require('/usr/lib/node_modules/@cyclonedx/cdxgen/node_modules/tar/package.json');if(p.version!=='7.5.19'){throw new Error('tar override failed: '+p.version)}" \
# Force brace-expansion >= 5.0.9 and ip-address >= 10.3.1 (CVE-2026-69152
# HIGH, CVE-2026-69192). Neither is suppressible as unreached: cdxgen puts
# values it read from the SCANNED repository into glob patterns, and the
# brace-expansion flaw is an uncatchable OOM, so an upstream try/catch
# would not contain it either.
#
# Unlike the tar swap above these are TRANSITIVE, and they land in more
# than one tree: cdxgen's own node_modules AND npm's. The sweep therefore
# walks all of /usr/lib/node_modules, rewrites every copy, and verifies
# each — a surviving stale copy fails the build rather than shipping
# quietly. Both bumps are patch-level on the same major, so no dependency
# range moves and no re-resolution runs.
#
# Scoping this to cdxgen's subtree was the first attempt and it swept
# nothing: cdxgen's own copies are already current, and both findings sit
# under npm's tree instead. A sweep that finds nothing looks identical to
# a sweep that fixed everything, which is why the verification below runs
# per directory rather than once at the end.
#
# Drop this when the cdxgen pin moves to a release carrying the fixes.
&& for spec in "[email protected]" "[email protected]"; do \
name="${spec%@*}"; ver="${spec##*@}"; \
npm pack "$spec" --pack-destination /tmp; \
for dir in $(find /usr/lib/node_modules -type d -name "$name" -prune -print); do \
rm -rf "$dir"; \
mkdir -p "$dir"; \
tar -xzf "/tmp/${name}-${ver}.tgz" --strip-components=1 -C "$dir"; \
got=$(node -p "require('${dir}/package.json').version"); \
if [ "$got" != "$ver" ]; then \
echo "override failed: ${dir} is ${got}, want ${ver}" >&2; \
exit 1; \
fi; \
done; \
rm -f "/tmp/${name}-${ver}.tgz"; \
done \
&& cdxgen --version

# ---- Trivy 0.72.0 (Apache-2.0). --------------------------------------------
Expand Down
4 changes: 3 additions & 1 deletion apps/backend/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ pyasn1==0.6.4
# future jose bump from silently moving the Fernet surface out from under us.
# 2026-06-16 bump 48.0.0 → 48.0.1: fixes GHSA-537c-gmf6-5ccf (HIGH — vulnerable
# OpenSSL statically included in the cryptography wheels).
cryptography==48.0.1
# 2026-08-04 bump 48.0.1 → 50.0.0: CVE-2026-69247 (HIGH) and CVE-2026-69249.
# 50.0.0 is the floor for the first; 49.0.0 would only clear the second.
cryptography==50.0.0
slowapi==0.1.9
email-validator==2.2.0
# Phase 6 PR #18 — async SMTP for the notifications module. aiosmtplib is the
Expand Down
Loading