Просмотр исходного кода

chore: security patches for dependency chain (#4708)

Andrew Bastin 1 месяц назад
Родитель
Сommit
8758cba109
3 измененных файлов с 136 добавлено и 84 удалено
  1. 4 1
      package.json
  2. 43 51
      pnpm-lock.yaml
  3. 89 32
      prod.Dockerfile

+ 4 - 1
package.json

@@ -44,8 +44,11 @@
       "pug": "3.0.3",
       "body-parser": "1.20.3",
       "path-to-regexp@3.2.0": "3.3.0",
+      "path-to-regexp@0.1.10": "0.1.12",
       "micromatch@<4.0.8": "4.0.8",
-      "dset@3.1.3": "3.1.4"
+      "dset@3.1.3": "3.1.4",
+      "nanoid@3.3.7": "3.3.8",
+      "execa@0.10.0": "2.0.0"
     },
     "packageExtensions": {
       "@hoppscotch/httpsnippet": {

+ 43 - 51
pnpm-lock.yaml

@@ -15,8 +15,11 @@ overrides:
   pug: 3.0.3
   body-parser: 1.20.3
   path-to-regexp@3.2.0: 3.3.0
+  path-to-regexp@0.1.10: 0.1.12
   micromatch@<4.0.8: 4.0.8
   dset@3.1.3: 3.1.4
+  nanoid@3.3.7: 3.3.8
+  execa@0.10.0: 2.0.0
 
 packageExtensionsChecksum: da57d58cd55bf5e7924e59ad5f1485b8
 
@@ -7493,9 +7496,9 @@ packages:
     resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
     engines: {node: '>=0.8.x'}
 
-  execa@0.10.0:
-    resolution: {integrity: sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==}
-    engines: {node: '>=4'}
+  execa@2.0.0:
+    resolution: {integrity: sha512-+ym7S09yUVPHEhYBsdLm53ZjCmCSeAQVtM/iN9dDj9tbvcBnCeBXTXHPWR9HXzht+vslGROteM8bSUdr4YszUg==}
+    engines: {node: '>=8'}
 
   execa@5.1.1:
     resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
@@ -7794,9 +7797,9 @@ packages:
     resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==}
     engines: {node: '>=8'}
 
-  get-stream@3.0.0:
-    resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==}
-    engines: {node: '>=4'}
+  get-stream@5.2.0:
+    resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
+    engines: {node: '>=8'}
 
   get-stream@6.0.1:
     resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
@@ -8412,10 +8415,6 @@ packages:
     resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==}
     engines: {node: '>= 0.4'}
 
-  is-stream@1.1.0:
-    resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==}
-    engines: {node: '>=0.10.0'}
-
   is-stream@2.0.1:
     resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
     engines: {node: '>=8'}
@@ -9429,8 +9428,8 @@ packages:
     engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
     hasBin: true
 
-  nanoid@3.3.7:
-    resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+  nanoid@3.3.8:
+    resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
     engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
     hasBin: true
 
@@ -9525,9 +9524,9 @@ packages:
     engines: {node: '>= 4'}
     hasBin: true
 
-  npm-run-path@2.0.2:
-    resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==}
-    engines: {node: '>=4'}
+  npm-run-path@3.1.0:
+    resolution: {integrity: sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==}
+    engines: {node: '>=8'}
 
   npm-run-path@4.0.1:
     resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
@@ -9654,6 +9653,10 @@ packages:
     resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==}
     engines: {node: '>=4'}
 
+  p-finally@2.0.1:
+    resolution: {integrity: sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==}
+    engines: {node: '>=8'}
+
   p-limit@2.3.0:
     resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
     engines: {node: '>=6'}
@@ -9811,10 +9814,6 @@ packages:
     resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
     engines: {node: '>=0.10.0'}
 
-  path-key@2.0.1:
-    resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==}
-    engines: {node: '>=4'}
-
   path-key@3.1.1:
     resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
     engines: {node: '>=8'}
@@ -9842,8 +9841,8 @@ packages:
     resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==}
     engines: {node: 20 || >=22}
 
-  path-to-regexp@0.1.10:
-    resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==}
+  path-to-regexp@0.1.12:
+    resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==}
 
   path-to-regexp@3.3.0:
     resolution: {integrity: sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==}
@@ -11033,10 +11032,6 @@ packages:
     resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==}
     engines: {node: '>=10'}
 
-  strip-eof@1.0.0:
-    resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==}
-    engines: {node: '>=0.10.0'}
-
   strip-final-newline@2.0.0:
     resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
     engines: {node: '>=6'}
@@ -20225,15 +20220,16 @@ snapshots:
 
   events@3.3.0: {}
 
-  execa@0.10.0:
+  execa@2.0.0:
     dependencies:
       cross-spawn: 7.0.6
-      get-stream: 3.0.0
-      is-stream: 1.1.0
-      npm-run-path: 2.0.2
-      p-finally: 1.0.0
+      get-stream: 5.2.0
+      is-stream: 2.0.1
+      merge-stream: 2.0.0
+      npm-run-path: 3.1.0
+      p-finally: 2.0.1
       signal-exit: 3.0.7
-      strip-eof: 1.0.0
+      strip-final-newline: 2.0.0
     optional: true
 
   execa@5.1.1:
@@ -20318,7 +20314,7 @@ snapshots:
       methods: 1.1.2
       on-finished: 2.4.1
       parseurl: 1.3.3
-      path-to-regexp: 0.1.10
+      path-to-regexp: 0.1.12
       proxy-addr: 2.0.7
       qs: 6.11.0
       range-parser: 1.2.1
@@ -20354,7 +20350,7 @@ snapshots:
       methods: 1.1.2
       on-finished: 2.4.1
       parseurl: 1.3.3
-      path-to-regexp: 0.1.10
+      path-to-regexp: 0.1.12
       proxy-addr: 2.0.7
       qs: 6.13.0
       range-parser: 1.2.1
@@ -20390,7 +20386,7 @@ snapshots:
       methods: 1.1.2
       on-finished: 2.4.1
       parseurl: 1.3.3
-      path-to-regexp: 0.1.10
+      path-to-regexp: 0.1.12
       proxy-addr: 2.0.7
       qs: 6.13.0
       range-parser: 1.2.1
@@ -20702,7 +20698,9 @@ snapshots:
   get-port@5.1.1:
     optional: true
 
-  get-stream@3.0.0:
+  get-stream@5.2.0:
+    dependencies:
+      pump: 3.0.0
     optional: true
 
   get-stream@6.0.1: {}
@@ -21440,9 +21438,6 @@ snapshots:
     dependencies:
       call-bind: 1.0.7
 
-  is-stream@1.1.0:
-    optional: true
-
   is-stream@2.0.1: {}
 
   is-stream@3.0.0: {}
@@ -23130,7 +23125,7 @@ snapshots:
 
   nanoid@3.3.1: {}
 
-  nanoid@3.3.7: {}
+  nanoid@3.3.8: {}
 
   napi-build-utils@1.0.2: {}
 
@@ -23209,9 +23204,9 @@ snapshots:
       shell-quote: 1.8.1
       string.prototype.padend: 3.1.6
 
-  npm-run-path@2.0.2:
+  npm-run-path@3.1.0:
     dependencies:
-      path-key: 2.0.1
+      path-key: 3.1.1
     optional: true
 
   npm-run-path@4.0.1:
@@ -23346,6 +23341,9 @@ snapshots:
   p-finally@1.0.0:
     optional: true
 
+  p-finally@2.0.1:
+    optional: true
+
   p-limit@2.3.0:
     dependencies:
       p-try: 2.2.0
@@ -23509,9 +23507,6 @@ snapshots:
 
   path-is-absolute@1.0.1: {}
 
-  path-key@2.0.1:
-    optional: true
-
   path-key@3.1.1: {}
 
   path-key@4.0.0: {}
@@ -23534,7 +23529,7 @@ snapshots:
       lru-cache: 11.0.1
       minipass: 7.1.2
 
-  path-to-regexp@0.1.10: {}
+  path-to-regexp@0.1.12: {}
 
   path-to-regexp@3.3.0: {}
 
@@ -23874,13 +23869,13 @@ snapshots:
 
   postcss@8.4.32:
     dependencies:
-      nanoid: 3.3.7
+      nanoid: 3.3.8
       picocolors: 1.1.0
       source-map-js: 1.2.1
 
   postcss@8.4.47:
     dependencies:
-      nanoid: 3.3.7
+      nanoid: 3.3.8
       picocolors: 1.1.0
       source-map-js: 1.2.1
 
@@ -24387,7 +24382,7 @@ snapshots:
 
   run-applescript@3.2.0:
     dependencies:
-      execa: 0.10.0
+      execa: 2.0.0
     optional: true
 
   run-applescript@5.0.0:
@@ -24865,9 +24860,6 @@ snapshots:
 
   strip-comments@2.0.1: {}
 
-  strip-eof@1.0.0:
-    optional: true
-
   strip-final-newline@2.0.0: {}
 
   strip-final-newline@3.0.0: {}

+ 89 - 32
prod.Dockerfile

@@ -1,11 +1,44 @@
-FROM node:20-alpine3.19 AS base_builder
+# This step is used to build a custom build of Caddy to prevent
+# vulnerable packages on the dependency chain
+FROM alpine:3.21.2 AS caddy_builder
+RUN apk add curl go
+
+RUN mkdir -p /tmp/caddy-build
+
+RUN curl -L -o /tmp/caddy-build/src.tar.gz https://github.com/caddyserver/caddy/releases/download/v2.9.1/caddy_2.9.1_src.tar.gz
+
+# Checksum verification of caddy source
+RUN expected="1cfd6127f9ed8dc908d84d7d14579d3ce5114e8671aa8f786745cb3fe60923e0" && \
+    actual=$(sha256sum /tmp/caddy-build/src.tar.gz | cut -d' ' -f1) && \
+    [ "$actual" = "$expected" ] && \
+    echo "✅ Caddy Source Checksum OK" || \
+    (echo "❌ Caddy Source Checksum failed!" && exit 1)
+
+WORKDIR /tmp/caddy-build
+RUN tar xvf /tmp/caddy-build/src.tar.gz
+
+# Patch to resolve CVE-2024-45339 on glog
+RUN go get github.com/golang/glog@v1.2.4
+RUN go mod vendor
+
+WORKDIR /tmp/caddy-build/cmd/caddy
+RUN go build
+
+
+
+FROM alpine:3.19.6 AS base_builder
+RUN apk add nodejs curl
+
+# Install NPM from source, as Alpine version is old and has dependency vulnerabilities
+# TODO: Find a better method which is resistant to supply chain attacks
+RUN sh -c "curl -qL https://www.npmjs.com/install.sh | env npm_install=10.9.2 sh"
 
 WORKDIR /usr/src/app
 
 ENV HOPP_ALLOW_RUNTIME_ENV=true
 
 # Required by @hoppscotch/js-sandbox to build `isolated-vm`
-RUN apk add python3 make g++
+RUN apk add python3 make g++ zlib-dev brotli-dev c-ares-dev nghttp2-dev openssl-dev icu-dev
 
 RUN npm install -g pnpm
 COPY pnpm-lock.yaml .
@@ -14,12 +47,7 @@ RUN pnpm fetch
 COPY . .
 RUN pnpm install -f --offline
 
-RUN npm uninstall -g cross-spawn && \
-    npm cache clean --force && \
-    # Remove any remaining old versions
-    find /usr/local/lib/node_modules -name "cross-spawn" -type d -exec rm -rf {} + && \
-    # Install cross-spawn v7 globally
-    npm install -g cross-spawn@^7.0.6 --force
+
 
 FROM base_builder AS backend_builder
 WORKDIR /usr/src/app/packages/hoppscotch-backend
@@ -29,16 +57,17 @@ RUN pnpm --filter=hoppscotch-backend deploy /dist/backend --prod
 WORKDIR /dist/backend
 RUN pnpm exec prisma generate
 
-FROM node:20-alpine3.19 AS backend
-RUN apk add caddy
-RUN npm install -g pnpm
+FROM alpine:3.19.6 AS backend
+RUN apk add nodejs curl
+
+# Install NPM from source, as Alpine version is old and has dependency vulnerabilities
+# TODO: Find a better method which is resistant to supply chain attacks
+RUN sh -c "curl -qL https://www.npmjs.com/install.sh | env npm_install=10.9.2 sh"
 
-RUN npm uninstall -g cross-spawn && \
-    npm cache clean --force && \
-    # Remove any remaining old versions
-    find /usr/local/lib/node_modules -name "cross-spawn" -type d -exec rm -rf {} + && \
-    # Install cross-spawn v7 globally
-    npm install -g cross-spawn@^7.0.6 --force
+# Install caddy
+COPY --from=caddy_builder /tmp/caddy-build/cmd/caddy/caddy /usr/bin/caddy
+
+RUN npm install -g pnpm
 
 COPY --from=base_builder  /usr/src/app/packages/hoppscotch-backend/backend.Caddyfile /etc/caddy/backend.Caddyfile
 COPY --from=backend_builder /dist/backend /dist/backend
@@ -56,16 +85,29 @@ CMD ["node", "prod_run.mjs"]
 EXPOSE 80
 EXPOSE 3170
 
+
+
 FROM base_builder AS fe_builder
 WORKDIR /usr/src/app/packages/hoppscotch-selfhost-web
 RUN pnpm run generate
 
-FROM caddy:2-alpine AS app
+
+
+
+FROM alpine:3.19.6 AS app
+RUN apk add nodejs curl
+
+# Install NPM from source, as Alpine version is old and has dependency vulnerabilities
+# TODO: Find a better method which is resistant to supply chain attacks
+RUN sh -c "curl -qL https://www.npmjs.com/install.sh | env npm_install=10.9.2 sh"
+
+# Install caddy
+COPY --from=caddy_builder /tmp/caddy-build/cmd/caddy/caddy /usr/bin/caddy
+
 COPY --from=fe_builder /usr/src/app/packages/hoppscotch-selfhost-web/prod_run.mjs /site/prod_run.mjs
 COPY --from=fe_builder /usr/src/app/packages/hoppscotch-selfhost-web/selfhost-web.Caddyfile /etc/caddy/selfhost-web.Caddyfile
 COPY --from=fe_builder /usr/src/app/packages/hoppscotch-selfhost-web/dist/ /site/selfhost-web
 
-RUN apk add nodejs npm
 
 RUN npm install -g @import-meta-env/cli
 
@@ -76,13 +118,29 @@ WORKDIR /site
 
 CMD ["/bin/sh", "-c", "node /site/prod_run.mjs && caddy run --config /etc/caddy/selfhost-web.Caddyfile --adapter caddyfile"]
 
+
+
+
+
 FROM base_builder AS sh_admin_builder
 WORKDIR /usr/src/app/packages/hoppscotch-sh-admin
 # Generate two builds for `sh-admin`, one based on subpath-access and the regular build
 RUN pnpm run build --outDir dist-multiport-setup
 RUN pnpm run build --outDir dist-subpath-access --base /admin/
 
-FROM caddy:2-alpine AS sh_admin
+
+
+
+
+FROM alpine:3.19.6 AS sh_admin
+RUN apk add nodejs curl
+
+# Install NPM from source, as Alpine version is old and has dependency vulnerabilities
+# TODO: Find a better method which is resistant to supply chain attacks
+RUN sh -c "curl -qL https://www.npmjs.com/install.sh | env npm_install=10.9.2 sh"
+
+# Install caddy
+COPY --from=caddy_builder /tmp/caddy-build/cmd/caddy/caddy /usr/bin/caddy
 
 COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/prod_run.mjs /site/prod_run.mjs
 COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/sh-admin-multiport-setup.Caddyfile /etc/caddy/sh-admin-multiport-setup.Caddyfile
@@ -90,7 +148,6 @@ COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/sh-admin-
 COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/dist-multiport-setup /site/sh-admin-multiport-setup
 COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/dist-subpath-access /site/sh-admin-subpath-access
 
-RUN apk add nodejs npm
 
 RUN npm install -g @import-meta-env/cli
 
@@ -101,7 +158,16 @@ WORKDIR /site
 
 CMD ["node","/site/prod_run.mjs"]
 
-FROM node:20-alpine3.19 AS aio
+FROM alpine:3.19.6 AS aio
+
+RUN apk add nodejs curl
+
+# Install NPM from source, as Alpine version is old and has dependency vulnerabilities
+# TODO: Find a better method which is resistant to supply chain attacks
+RUN sh -c "curl -qL https://www.npmjs.com/install.sh | env npm_install=10.9.2 sh"
+
+# Caddy install
+COPY --from=caddy_builder /tmp/caddy-build/cmd/caddy/caddy /usr/bin/caddy
 
 ENV PRODUCTION="true"
 ENV PORT=8080
@@ -113,18 +179,9 @@ LABEL org.opencontainers.image.source="https://github.com/hoppscotch/hoppscotch"
   org.opencontainers.image.url="https://docs.hoppscotch.io" \
   org.opencontainers.image.licenses="MIT"
 
-# Run this separately to use the cache from backend
-RUN apk add caddy
-
-RUN apk add tini curl
+RUN apk add tini
 
 RUN npm install -g pnpm
-RUN npm uninstall -g cross-spawn && \
-    npm cache clean --force && \
-    # Remove any remaining old versions
-    find /usr/local/lib/node_modules -name "cross-spawn" -type d -exec rm -rf {} + && \
-    # Install cross-spawn v7 globally
-    npm install -g cross-spawn@^7.0.6 --force
 
 # Copy necessary files
 # Backend files