diff --git a/server-ce/hotfix/4.2.5/Dockerfile b/server-ce/hotfix/4.2.5/Dockerfile new file mode 100644 index 0000000000..b140c0d990 --- /dev/null +++ b/server-ce/hotfix/4.2.5/Dockerfile @@ -0,0 +1,29 @@ +FROM sharelatex/sharelatex:4.2.4 + +# apply an override to the swagger-tools package to force security updates to multer and qs +# from https://github.com/overleaf/internal/pull/18433 +COPY pr_18433.patch . +RUN patch -p1 < pr_18433.patch && rm pr_18433.patch +RUN npm install --include-workspace-root -w services/history-v1 swagger-tools@0.10.4 && rm -rf /root/.cache /root/.npm $(find /tmp/ -mindepth 1 -maxdepth 1) + +# remove google-cloud packages which are unused in server-pro have a vulnerable dependency +RUN npm uninstall -w libraries/logger @google-cloud/logging-bunyan +RUN npm uninstall -w libraries/metrics @google-cloud/opentelemetry-cloud-trace-exporter @google-cloud/profiler + +# the passport-twitter package has been removed from the monorepo +RUN npm uninstall -w services/web passport-twitter + +# remove the unused services/web/scripts/translations directory +RUN rm -r services/web/scripts/translations + +COPY pr_18393.patch . +RUN patch -p1 < pr_18393.patch && rm pr_18393.patch +COPY pr_18444.patch . +RUN patch -p1 < pr_18444.patch && rm pr_18444.patch +COPY pr_18819.patch . +RUN patch -p1 < pr_18819.patch && rm pr_18819.patch +COPY pr_18570.patch . +RUN patch -p1 < pr_18570.patch && rm pr_18570.patch + +# Recompile frontend assets +RUN node genScript compile | bash diff --git a/server-ce/hotfix/4.2.5/pr_18393.patch b/server-ce/hotfix/4.2.5/pr_18393.patch new file mode 100644 index 0000000000..5af1af7750 --- /dev/null +++ b/server-ce/hotfix/4.2.5/pr_18393.patch @@ -0,0 +1,111 @@ +diff --git a/services/web/frontend/js/features/source-editor/components/command-tooltip/href-tooltip.tsx b/services/web/frontend/js/features/source-editor/components/command-tooltip/href-tooltip.tsx +index a0d681d9cb5..2f9a4333cd6 100644 +--- a/services/web/frontend/js/features/source-editor/components/command-tooltip/href-tooltip.tsx ++++ b/services/web/frontend/js/features/source-editor/components/command-tooltip/href-tooltip.tsx +@@ -17,6 +17,7 @@ import { + import { Button, ControlLabel, FormControl, FormGroup } from 'react-bootstrap' + import Icon from '../../../../shared/components/icon' + import { EditorState } from '@codemirror/state' ++import { openURL } from '@/features/source-editor/utils/url' + + export const HrefTooltipContent: FC = () => { + const state = useCodeMirrorStateContext() +@@ -108,7 +109,7 @@ export const HrefTooltipContent: FC = () => { + className="ol-cm-command-tooltip-link" + onClick={() => { + // TODO: unescape content +- window.open(url, '_blank') ++ openURL(url) + }} + > + +diff --git a/services/web/frontend/js/features/source-editor/components/command-tooltip/url-tooltip.tsx b/services/web/frontend/js/features/source-editor/components/command-tooltip/url-tooltip.tsx +index c51b497de01..632d71dd031 100644 +--- a/services/web/frontend/js/features/source-editor/components/command-tooltip/url-tooltip.tsx ++++ b/services/web/frontend/js/features/source-editor/components/command-tooltip/url-tooltip.tsx +@@ -9,6 +9,7 @@ import { + } from '../../lezer-latex/latex.terms.mjs' + import Icon from '../../../../shared/components/icon' + import { EditorState } from '@codemirror/state' ++import { openURL } from '@/features/source-editor/utils/url' + + export const UrlTooltipContent: FC = () => { + const { t } = useTranslation() +@@ -23,7 +24,7 @@ export const UrlTooltipContent: FC = () => { + onClick={() => { + const url = readUrl(state) + if (url) { +- window.open(url, '_blank') ++ openURL(url) + } + }} + > +diff --git a/services/web/frontend/js/features/source-editor/utils/url.ts b/services/web/frontend/js/features/source-editor/utils/url.ts +new file mode 100644 +index 00000000000..8bfc9bdeab8 +--- /dev/null ++++ b/services/web/frontend/js/features/source-editor/utils/url.ts +@@ -0,0 +1,11 @@ ++const ALLOWED_PROTOCOLS = ['https:', 'http:'] ++ ++export const openURL = (content: string) => { ++ const url = new URL(content, document.location.href) ++ ++ if (!ALLOWED_PROTOCOLS.includes(url.protocol)) { ++ throw new Error(`Not opening URL with protocol ${url.protocol}`) ++ } ++ ++ window.open(url, '_blank') ++} +diff --git a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-command-tooltip.spec.tsx b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-command-tooltip.spec.tsx +index 837f90a64ab..d46b522a116 100644 +--- a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-command-tooltip.spec.tsx ++++ b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-command-tooltip.spec.tsx +@@ -54,8 +54,8 @@ describe(' command tooltip in Visual mode', function () { + // open the link + cy.findByRole('button', { name: 'Go to page' }).click() + cy.get('@window-open').should( +- 'have.been.calledOnceWithExactly', +- 'https://example.com', ++ 'have.been.calledWithMatch', ++ Cypress.sinon.match.has('href', 'https://example.com/'), + '_blank' + ) + +@@ -112,8 +112,8 @@ describe(' command tooltip in Visual mode', function () { + // open the link + cy.findByRole('button', { name: 'Go to page' }).click() + cy.get('@window-open').should( +- 'have.been.calledOnceWithExactly', +- 'https://example.com', ++ 'have.been.calledWithMatch', ++ Cypress.sinon.match.has('href', 'https://example.com/'), + '_blank' + ) + }) +diff --git a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-tooltips.spec.tsx b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-tooltips.spec.tsx +index c6e28f9eeeb..106a80ba187 100644 +--- a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-tooltips.spec.tsx ++++ b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-tooltips.spec.tsx +@@ -42,8 +42,8 @@ describe(' tooltips in Visual mode', function () { + }) + cy.findByRole('button', { name: 'Go to page' }).click() + cy.get('@open-window').should( +- 'have.been.calledOnceWithExactly', +- 'https://example.com/foo', ++ 'have.been.calledWithMatch', ++ Cypress.sinon.match.has('href', 'https://example.com/foo'), + '_blank' + ) + cy.findByRole('button', { name: 'Remove link' }).click() +@@ -62,8 +62,8 @@ describe(' tooltips in Visual mode', function () { + }) + cy.findByRole('button', { name: 'Go to page' }).click() + cy.get('@open-window').should( +- 'have.been.calledOnceWithExactly', +- 'https://example.com', ++ 'have.been.calledWithMatch', ++ Cypress.sinon.match.has('href', 'https://example.com/'), + '_blank' + ) + }) diff --git a/server-ce/hotfix/4.2.5/pr_18433.patch b/server-ce/hotfix/4.2.5/pr_18433.patch new file mode 100644 index 0000000000..1e14f239ab --- /dev/null +++ b/server-ce/hotfix/4.2.5/pr_18433.patch @@ -0,0 +1,63 @@ +diff --git a/package-lock.json b/package-lock.json +index b9eba6086b..bb1a5cebaf 100644 +--- a/package-lock.json ++++ b/package-lock.json +@@ -70674,8 +70674,7 @@ + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "multer": { +- "version": "1.4.4", +- "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", ++ "version": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", + "requires": { + "append-field": "^1.0.0", +@@ -76995,10 +76994,10 @@ + "js-yaml": "^3.3.1", + "json-refs": "^3.0.2", + "lodash": "^4.17.4", +- "multer": "^1.1.0", ++ "multer": "1.4.5-lts.1", + "parseurl": "^1.3.0", + "path-to-regexp": "^2.0.0", +- "qs": "^6.0.3", ++ "qs": "6.5.3", + "serve-static": "^1.10.0", + "spark-md5": "^3.0.0", + "superagent": "^3.5.2", +@@ -77035,7 +77034,7 @@ + "http-errors": "~1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "~2.3.0", +- "qs": "6.5.1", ++ "qs": "6.5.3", + "raw-body": "2.3.2", + "type-is": "~1.6.15" + }, +@@ -77109,8 +77108,7 @@ + "integrity": "sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==" + }, + "qs": { +- "version": "6.5.1", +- "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", ++ "version": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "raw-body": { +diff --git a/package.json b/package.json +index f092472caf..329d4fc5ce 100644 +--- a/package.json ++++ b/package.json +@@ -1,6 +1,12 @@ + { + "name": "overleaf", + "private": true, ++ "overrides": { ++ "swagger-tools": { ++ "multer": "1.4.5-lts.1", ++ "qs": "6.5.3" ++ } ++ }, + "dependencies": { + "patch-package": "^8.0.0" + }, diff --git a/server-ce/hotfix/4.2.5/pr_18444.patch b/server-ce/hotfix/4.2.5/pr_18444.patch new file mode 100644 index 0000000000..e79fe18550 --- /dev/null +++ b/server-ce/hotfix/4.2.5/pr_18444.patch @@ -0,0 +1,41 @@ +diff --git a/services/web/frontend/js/features/file-view/components/file-view-pdf.tsx b/services/web/frontend/js/features/file-view/components/file-view-pdf.tsx +index 4d3b80bb9a2..3efc61a2199 100644 +--- a/services/web/frontend/js/features/file-view/components/file-view-pdf.tsx ++++ b/services/web/frontend/js/features/file-view/components/file-view-pdf.tsx +@@ -33,7 +33,10 @@ const FileViewPdf: FC<{ + return + } + +- const pdf = await PDFJS.getDocument(preview.url).promise ++ const pdf = await PDFJS.getDocument({ ++ url: preview.url, ++ isEvalSupported: false, ++ }).promise + + // bail out if loading the PDF took too long + if (!mountedRef.current) { +diff --git a/services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.js b/services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.js +index 9b419b1397f..6a92630a215 100644 +--- a/services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.js ++++ b/services/web/frontend/js/features/pdf-preview/util/pdf-js-wrapper.js +@@ -96,6 +96,7 @@ export default class PDFJSWrapper { + rangeChunkSize, + disableAutoFetch: true, + disableStream, ++ isEvalSupported: false, + textLayerMode: 2, // PDFJSViewer.TextLayerMode.ENABLE, + range: rangeTransport, + }) +diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/graphics.ts b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/graphics.ts +index 7321f9e02b5..f6c744aaec2 100644 +--- a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/graphics.ts ++++ b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/graphics.ts +@@ -143,7 +143,7 @@ export class GraphicsWidget extends WidgetType { + return + } + +- const pdf = await PDFJS.getDocument(url).promise ++ const pdf = await PDFJS.getDocument({ url, isEvalSupported: false }).promise + const page = await pdf.getPage(1) + + // bail out if loading the PDF took too long diff --git a/server-ce/hotfix/4.2.5/pr_18570.patch b/server-ce/hotfix/4.2.5/pr_18570.patch new file mode 100644 index 0000000000..05bc9f5531 --- /dev/null +++ b/server-ce/hotfix/4.2.5/pr_18570.patch @@ -0,0 +1,30 @@ +--- a/genScript.js ++++ b/genScript.js +@@ -5,16 +5,26 @@ console.log('set -ex') + + switch (process.argv.pop()) { + case 'install': +- console.log('npm ci') ++ console.log('npm install --omit=dev') + break + case 'compile': + for (const service of services) { + console.log('pushd', `services/${service.name}`) + switch (service.name) { + case 'web': ++ // Avoid downloading of cypress ++ console.log('export CYPRESS_INSTALL_BINARY=0') ++ ++ // install webpack and frontend dependencies ++ console.log('npm install --include=dev') ++ // install misplaced dependencies (fixed via 18389) ++ console.log('pushd ../../ && npm install --include=dev --workspaces=false && popd') ++ // run webpack + console.log('npm run webpack:production') + // drop webpack/babel cache + console.log('rm -rf node_modules/.cache') ++ // uninstall webpack and frontend dependencies ++ console.log('pushd ../../ && npm install --omit=dev && popd') + break + default: + console.log(`echo ${service.name} does not require a compilation`) diff --git a/server-ce/hotfix/4.2.5/pr_18819.patch b/server-ce/hotfix/4.2.5/pr_18819.patch new file mode 100644 index 0000000000..858c044ea5 --- /dev/null +++ b/server-ce/hotfix/4.2.5/pr_18819.patch @@ -0,0 +1,17 @@ +--- a/services/web/frontend/js/features/mathjax/load-mathjax.ts ++++ b/services/web/frontend/js/features/mathjax/load-mathjax.ts +@@ -36,6 +36,15 @@ export const loadMathJax = async () => { + }, + startup: { + typeset: false, ++ ready() { ++ window.MathJax.startup.defaultReady() ++ const safe = window.MathJax.startup.document.safe ++ safe.filterAttributes.set('fontfamily', 'filterFontFamily') ++ safe.filterMethods.filterFontFamily = ( ++ _safe: any, ++ family: string ++ ) => family.split(/;/)[0] ++ }, + }, + } diff --git a/server-ce/hotfix/5.0.5/Dockerfile b/server-ce/hotfix/5.0.5/Dockerfile new file mode 100644 index 0000000000..b9ad108a26 --- /dev/null +++ b/server-ce/hotfix/5.0.5/Dockerfile @@ -0,0 +1,12 @@ +FROM sharelatex/sharelatex:5.0.4 + +# Install dev dependencies as part of "genScript compile" +COPY pr_18570.patch . +RUN patch -p1 < pr_18570.patch && rm pr_18570.patch + +# Adopted from https://github.com/overleaf/internal/pull/18819 +COPY pr_18819.patch . +RUN patch -p1 < pr_18819.patch && rm pr_18819.patch + +# Recompile frontend assets +RUN node genScript compile | bash diff --git a/server-ce/hotfix/5.0.5/pr_18570.patch b/server-ce/hotfix/5.0.5/pr_18570.patch new file mode 100644 index 0000000000..05bc9f5531 --- /dev/null +++ b/server-ce/hotfix/5.0.5/pr_18570.patch @@ -0,0 +1,30 @@ +--- a/genScript.js ++++ b/genScript.js +@@ -5,16 +5,26 @@ console.log('set -ex') + + switch (process.argv.pop()) { + case 'install': +- console.log('npm ci') ++ console.log('npm install --omit=dev') + break + case 'compile': + for (const service of services) { + console.log('pushd', `services/${service.name}`) + switch (service.name) { + case 'web': ++ // Avoid downloading of cypress ++ console.log('export CYPRESS_INSTALL_BINARY=0') ++ ++ // install webpack and frontend dependencies ++ console.log('npm install --include=dev') ++ // install misplaced dependencies (fixed via 18389) ++ console.log('pushd ../../ && npm install --include=dev --workspaces=false && popd') ++ // run webpack + console.log('npm run webpack:production') + // drop webpack/babel cache + console.log('rm -rf node_modules/.cache') ++ // uninstall webpack and frontend dependencies ++ console.log('pushd ../../ && npm install --omit=dev && popd') + break + default: + console.log(`echo ${service.name} does not require a compilation`) diff --git a/server-ce/hotfix/5.0.5/pr_18819.patch b/server-ce/hotfix/5.0.5/pr_18819.patch new file mode 100644 index 0000000000..83525653da --- /dev/null +++ b/server-ce/hotfix/5.0.5/pr_18819.patch @@ -0,0 +1,17 @@ +--- a/services/web/frontend/js/features/mathjax/load-mathjax.ts ++++ b/services/web/frontend/js/features/mathjax/load-mathjax.ts +@@ -64,6 +64,15 @@ export const loadMathJax = async (options?: { + .findID('Renderer') + .disable() + }, ++ ready() { ++ window.MathJax.startup.defaultReady() ++ const safe = window.MathJax.startup.document.safe ++ safe.filterAttributes.set('fontfamily', 'filterFontFamily') ++ safe.filterMethods.filterFontFamily = ( ++ _safe: any, ++ family: string ++ ) => family.split(/;/)[0] ++ }, + }, + }