Skip to content

Commit b0d3572

Browse files
authored
fix(sandbox): patch bundled runtime dependencies (#84)
## Summary - advances the frozen Debian package snapshot to include the fixed Bookworm NSS build - updates the Expo template and document runtime away from vulnerable archive/glob dependencies - adds one integrity-locked security overlay for dependency trees embedded inside npm, pnpm, and code-server - verifies the resolved NSS and embedded package versions in the protected snapshot smoke test ## Context The first Node 24 snapshot run built successfully but Trivy correctly blocked publication. No Daytona snapshot was created. The scan found fixed vulnerabilities in Debian NSS, the Expo/document locks, and dependency trees that npm, pnpm, and code-server bundle internally and therefore cannot receive ordinary top-level overrides. ## Decisions | Decision | Choice | Reasoning | |---|---|---| | Debian fix | Frozen 2026-07-22 snapshot | This is after libnss3 2:3.87.1-1+deb12u3 first entered Debian Security on July 21 | | Document runtime | Upgrade archiver to 8.0.0 and unzipper to 0.12.5 | Removes the old glob/minimatch chain while preserving ExcelJS behavior | | Expo | Minimal pnpm override and lock update to brace-expansion 5.0.8 | Keeps the generated app graph stable and patched | | Embedded CLIs/editor | One lockfile-backed runtime security overlay | npm, pnpm, and code-server ship nested dependency trees that package-manager overrides do not replace | | Image layers | Patch in the same layer that installs/extracts upstream bundles | Vulnerable copies never survive in a committed image layer | | Scanner input | Remove the package-manager install lock from the runtime image | The source lock honestly records npm's upstream bundle; the final image contains only patched files | ## Verification - [x] original protected image build passed; publication was blocked at Trivy as designed - [x] full lint, typecheck, and production build pass under Node 24.18.0 - [x] architecture boundaries, dead-code scan, actionlint, and shellcheck pass - [x] Trivy Docker configuration scan: 0 findings - [x] Trivy lock scans for Expo, document runtime, and security overlay: 0 findings - [x] npm audits for document runtime and security overlay: 0 findings - [x] Expo production lock audit: 0 findings - [x] ExcelJS workbook write/read round trip passes with the upgraded archive stack - [x] patched npm, pnpm, and code-server package APIs and exact versions verified locally - [ ] protected final-image vulnerability/secret scan and runtime smoke test after merge - [ ] Daytona snapshot publication and direct production QA after promotion The repository still contains exactly one SQL migration file. This PR has no database or production data change. No Linear issue or plan document is associated with this production QA fix.
1 parent f62b80b commit b0d3572

8 files changed

Lines changed: 569 additions & 431 deletions

File tree

.github/workflows/build-snapshot.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,17 @@ jobs:
114114
test "$(id -un)" = node
115115
test "$PWD" = /workspace
116116
test "$(node --version)" = v24.18.0
117+
libnss_version="$(dpkg-query --show libnss3 | cut --fields=2)"
118+
dpkg --compare-versions "$libnss_version" ge "2:3.87.1-1+deb12u3"
119+
code_server_dir="$(dirname "$(dirname "$(readlink -f "$(command -v code-server)")")")"
120+
test "$(node -p "require(process.argv[1]).version" /opt/cheatcode-doc-runtime/node_modules/brace-expansion/package.json)" = 5.0.8
121+
test "$(node -p "require(process.argv[1]).version" /opt/cheatcode-package-manager/node_modules/npm/node_modules/brace-expansion/package.json)" = 5.0.8
122+
test "$(node -p "require(process.argv[1]).version" /opt/cheatcode-package-manager/node_modules/npm/node_modules/tar/package.json)" = 7.5.22
123+
test "$(node -p "require(process.argv[1]).version" /opt/cheatcode-package-manager/node_modules/pnpm/artifacts/exe/dist/node_modules/tar/package.json)" = 7.5.22
124+
test "$(node -p "require(process.argv[1]).version" /opt/cheatcode-package-manager/node_modules/pnpm/dist/node_modules/tar/package.json)" = 7.5.22
125+
test "$(node -p "require(process.argv[1]).version" "$code_server_dir/node_modules/js-yaml/package.json")" = 4.3.0
126+
test "$(node -p "require(process.argv[1]).version" "$code_server_dir/lib/vscode/node_modules/shell-quote/package.json")" = 1.10.0
127+
test "$(node -p "require(process.argv[1]).version" "$code_server_dir/lib/vscode/node_modules/tar/package.json")" = 7.5.22
117128
npm --version
118129
pnpm --version
119130
python3 --version

infra/containers/sandbox/Dockerfile

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ FROM node:24.18.0-bookworm-slim@sha256:6f7b03f7c2c8e2e784dcf9295400527b9b1270fd3
22

33
ARG CODE_SERVER_VERSION=4.128.0
44
ARG CODE_SERVER_SHA256=79ba26bf186e5268a22b7c17b30a5f288a16c37791f0b86c27859e8fef103188
5-
ARG DEBIAN_SNAPSHOT=20260718T000000Z
5+
ARG DEBIAN_SNAPSHOT=20260722T000000Z
66

77
# Daytona injects its own daemon (host-mounted, PID 1) and overrides ENTRYPOINT,
88
# so we do NOT bake a sandbox daemon. Headed Chromium uses Xvfb, which the
@@ -33,16 +33,35 @@ RUN set -eux; \
3333

3434
COPY package-manager/package.json package-manager/package-lock.json /opt/cheatcode-package-manager/
3535
COPY doc-runtime/package.json doc-runtime/package-lock.json /opt/cheatcode-doc-runtime/
36+
# npm, pnpm, and code-server ship their own dependency trees, so ordinary
37+
# top-level overrides cannot replace vulnerable packages inside those bundles.
38+
COPY runtime-security-overrides/package.json runtime-security-overrides/package-lock.json /opt/cheatcode-runtime-security-overrides/
3639
COPY skill-runtime/package.json skill-runtime/package-lock.json skill-runtime/tsconfig.json /opt/cheatcode-skill-runtime/
3740
COPY skill-runtime/bin/ /opt/cheatcode-skill-runtime/bin/
3841
COPY skill-runtime/src/ /opt/cheatcode-skill-runtime/src/
42+
WORKDIR /opt/cheatcode-runtime-security-overrides
43+
RUN npm ci --omit=dev --ignore-scripts --no-audit --no-fund
3944
WORKDIR /opt/cheatcode-package-manager
4045
RUN npm ci --omit=dev --ignore-scripts --no-audit --no-fund \
4146
&& rm -rf /usr/local/lib/node_modules/npm \
4247
&& ln -sf /opt/cheatcode-package-manager/node_modules/.bin/npm /usr/local/bin/npm \
4348
&& ln -sf /opt/cheatcode-package-manager/node_modules/.bin/npx /usr/local/bin/npx \
4449
&& ln -sf /opt/cheatcode-package-manager/node_modules/.bin/pnpm /usr/local/bin/pnpm \
45-
&& ln -sf /opt/cheatcode-package-manager/node_modules/.bin/pnpx /usr/local/bin/pnpx
50+
&& ln -sf /opt/cheatcode-package-manager/node_modules/.bin/pnpx /usr/local/bin/pnpx \
51+
&& rm -rf \
52+
/opt/cheatcode-package-manager/node_modules/npm/node_modules/brace-expansion \
53+
/opt/cheatcode-package-manager/node_modules/npm/node_modules/tar \
54+
/opt/cheatcode-package-manager/node_modules/pnpm/artifacts/exe/dist/node_modules/tar \
55+
/opt/cheatcode-package-manager/node_modules/pnpm/dist/node_modules/tar \
56+
&& cp -a /opt/cheatcode-runtime-security-overrides/node_modules/brace-expansion \
57+
/opt/cheatcode-package-manager/node_modules/npm/node_modules/brace-expansion \
58+
&& cp -a /opt/cheatcode-runtime-security-overrides/node_modules/tar \
59+
/opt/cheatcode-package-manager/node_modules/npm/node_modules/tar \
60+
&& cp -a /opt/cheatcode-runtime-security-overrides/node_modules/tar \
61+
/opt/cheatcode-package-manager/node_modules/pnpm/artifacts/exe/dist/node_modules/tar \
62+
&& cp -a /opt/cheatcode-runtime-security-overrides/node_modules/tar \
63+
/opt/cheatcode-package-manager/node_modules/pnpm/dist/node_modules/tar \
64+
&& rm -f /opt/cheatcode-package-manager/package-lock.json
4665
WORKDIR /opt/cheatcode-doc-runtime
4766
RUN npm ci --omit=dev --ignore-scripts --no-audit --no-fund \
4867
&& npm cache clean --force
@@ -61,7 +80,17 @@ RUN curl -fsSL \
6180
&& echo "${CODE_SERVER_SHA256} /tmp/code-server.tar.gz" | sha256sum --check --strict \
6281
&& tar -xzf /tmp/code-server.tar.gz -C /opt \
6382
&& ln -sf "/opt/code-server-${CODE_SERVER_VERSION}-linux-amd64/bin/code-server" /usr/local/bin/code-server \
64-
&& rm -f /tmp/code-server.tar.gz
83+
&& rm -f /tmp/code-server.tar.gz \
84+
&& rm -rf \
85+
"/opt/code-server-${CODE_SERVER_VERSION}-linux-amd64/node_modules/js-yaml" \
86+
"/opt/code-server-${CODE_SERVER_VERSION}-linux-amd64/lib/vscode/node_modules/shell-quote" \
87+
"/opt/code-server-${CODE_SERVER_VERSION}-linux-amd64/lib/vscode/node_modules/tar" \
88+
&& cp -a /opt/cheatcode-runtime-security-overrides/node_modules/js-yaml \
89+
"/opt/code-server-${CODE_SERVER_VERSION}-linux-amd64/node_modules/js-yaml" \
90+
&& cp -a /opt/cheatcode-runtime-security-overrides/node_modules/shell-quote \
91+
"/opt/code-server-${CODE_SERVER_VERSION}-linux-amd64/lib/vscode/node_modules/shell-quote" \
92+
&& cp -a /opt/cheatcode-runtime-security-overrides/node_modules/tar \
93+
"/opt/code-server-${CODE_SERVER_VERSION}-linux-amd64/lib/vscode/node_modules/tar"
6594

6695
COPY requirements.txt /tmp/requirements.txt
6796
RUN pip3 install --break-system-packages --disable-pip-version-check --no-cache-dir \

infra/containers/sandbox/app-templates/expo/pnpm-lock.yaml

Lines changed: 6 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

infra/containers/sandbox/app-templates/expo/pnpm-workspace.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ packages:
22
- .
33

44
overrides:
5+
'brace-expansion@<=5.0.7': 5.0.8
56
'uuid@<11.1.1': 11.1.1

0 commit comments

Comments
 (0)