[CE/SP] Hotfix 5.1.1 and 4.2.8 (#19771)

* [CE/SP] Hotfix 5.1.1 and 4.2.8

* Add script to build hotfix releases

GitOrigin-RevId: 8ece5e5fd5ec360b66069ce774319511ed82a13a
This commit is contained in:
Miguel Serrano 2024-08-13 15:15:09 +02:00 committed by Copybot
parent c117483761
commit e08057828f
11 changed files with 344 additions and 0 deletions

View file

@ -0,0 +1,11 @@
FROM sharelatex/sharelatex:4.2.7
# Fix crash on on invalid URLs
COPY pr_19612.patch .
RUN patch -p1 < pr_19612.patch && rm pr_19612.patch
COPY pr_19550.patch .
RUN patch -p1 < pr_19550.patch && rm pr_19550.patch
COPY is_19575.patch /etc/nginx/sites-enabled/
RUN cd /etc/nginx/sites-enabled && patch -p0 < is_19575.patch && rm is_19575.patch

View file

@ -0,0 +1,19 @@
--- sharelatex.conf
+++ sharelatex.conf
@@ -67,6 +67,16 @@ server {
proxy_http_version 1.1;
}
+ # block external access to metrics
+ location ~* ^/metrics/?$ {
+ return 404 'Not found';
+ }
+
+ # block external access to all health checks /health_check, /health_check/full, etc
+ location ~* ^/health_check {
+ return 404 'Not found';
+ }
+
# Load any extra configuration for this vhost
include /etc/nginx/vhost-extras/overleaf/*.conf;
}

View file

@ -0,0 +1,58 @@
diff --git a/services/web/app/src/infrastructure/CSP.js b/services/web/app/src/infrastructure/CSP.js
index 28f4f380d3d..abc11c59a48 100644
--- a/services/web/app/src/infrastructure/CSP.js
+++ b/services/web/app/src/infrastructure/CSP.js
@@ -6,6 +6,7 @@ module.exports = function ({
reportPercentage,
reportOnly = false,
exclude = [],
+ viewDirectives = {},
}) {
const header = reportOnly
? 'Content-Security-Policy-Report-Only'
@@ -33,7 +34,12 @@ module.exports = function ({
res.locals.scriptNonce = scriptNonce
- const policy = buildViewPolicy(scriptNonce, reportPercentage, reportUri)
+ const policy = buildViewPolicy(
+ scriptNonce,
+ reportPercentage,
+ reportUri,
+ viewDirectives[view]
+ )
// Note: https://csp-evaluator.withgoogle.com/ is useful for checking the policy
@@ -68,11 +74,17 @@ const buildDefaultPolicy = (reportUri, styleSrc) => {
return directives.join('; ')
}
-const buildViewPolicy = (scriptNonce, reportPercentage, reportUri) => {
+const buildViewPolicy = (
+ scriptNonce,
+ reportPercentage,
+ reportUri,
+ viewDirectives
+) => {
const directives = [
`script-src 'nonce-${scriptNonce}' 'unsafe-inline' 'strict-dynamic' https: 'report-sample'`, // only allow scripts from certain sources
`object-src 'none'`, // forbid loading an "object" element
`base-uri 'none'`, // forbid setting a "base" element
+ ...(viewDirectives ?? []),
]
if (reportUri) {
--- a/services/web/config/settings.defaults.js
+++ b/services/web/config/settings.defaults.js
@@ -868,6 +868,9 @@ module.exports = {
reportPercentage: parseFloat(process.env.CSP_REPORT_PERCENTAGE) || 0,
reportUri: process.env.CSP_REPORT_URI,
exclude: ['app/views/project/editor'],
+ viewDirectives: {
+ 'app/views/project/ide-react': [`img-src 'self' data: blob:`],
+ },
},
unsupportedBrowsers: {

View file

@ -0,0 +1,46 @@
diff --git a/services/web/app/src/Features/HealthCheck/HealthCheckController.js b/services/web/app/src/Features/HealthCheck/HealthCheckController.js
index 278f04bb767..ff074cfa816 100644
--- a/services/web/app/src/Features/HealthCheck/HealthCheckController.js
+++ b/services/web/app/src/Features/HealthCheck/HealthCheckController.js
@@ -45,6 +45,10 @@ module.exports = {
logger.err({ err }, 'failed api redis health check')
return res.sendStatus(500)
}
+ if (!settings.smokeTest.userId) {
+ logger.err({}, 'smokeTest.userId is undefined in health check')
+ return res.sendStatus(404)
+ }
UserGetter.getUserEmail(settings.smokeTest.userId, (err, email) => {
if (err) {
logger.err({ err }, 'failed api mongo health check')
diff --git a/services/web/app/src/infrastructure/ExpressLocals.js b/services/web/app/src/infrastructure/ExpressLocals.js
index 5f14977d3a3..2e9ed4f1ebb 100644
--- a/services/web/app/src/infrastructure/ExpressLocals.js
+++ b/services/web/app/src/infrastructure/ExpressLocals.js
@@ -11,6 +11,7 @@ const Features = require('./Features')
const SessionManager = require('../Features/Authentication/SessionManager')
const PackageVersions = require('./PackageVersions')
const Modules = require('./Modules')
+const Errors = require('../Features/Errors/Errors')
const {
canRedirectToAdminDomain,
hasAdminAccess,
@@ -236,10 +237,14 @@ module.exports = function (webRouter, privateApiRouter, publicApiRouter) {
// Don't include the query string parameters, otherwise Google
// treats ?nocdn=true as the canonical version
- const parsedOriginalUrl = new URL(req.originalUrl, Settings.siteUrl)
- res.locals.currentUrl = parsedOriginalUrl.pathname
- res.locals.currentUrlWithQueryParams =
- parsedOriginalUrl.pathname + parsedOriginalUrl.search
+ try {
+ const parsedOriginalUrl = new URL(req.originalUrl, Settings.siteUrl)
+ res.locals.currentUrl = parsedOriginalUrl.pathname
+ res.locals.currentUrlWithQueryParams =
+ parsedOriginalUrl.pathname + parsedOriginalUrl.search
+ } catch (err) {
+ return next(new Errors.InvalidError())
+ }
res.locals.capitalize = function (string) {
if (string.length === 0) {
return ''

View file

@ -0,0 +1,20 @@
FROM sharelatex/sharelatex:5.1.0
# Confirmation email fix
COPY pr_19676.patch .
RUN patch -p1 < pr_19676.patch && rm pr_19676.patch
# Fix crash on on invalid URLs
COPY pr_19612.patch .
RUN patch -p1 < pr_19612.patch && rm pr_19612.patch
# Remove Editor Resources check from launchpad
COPY pr_19543.patch .
RUN patch -p1 < pr_19543.patch && rm pr_19543.patch
COPY pr_19550.patch .
RUN patch -p1 < pr_19550.patch && rm pr_19550.patch
COPY is_19575.patch /etc/nginx/sites-enabled/
RUN cd /etc/nginx/sites-enabled && patch -p0 < is_19575.patch && rm is_19575.patch

View file

@ -0,0 +1,19 @@
--- overleaf.conf
+++ overleaf.conf
@@ -67,6 +67,16 @@ server {
proxy_http_version 1.1;
}
+ # block external access to metrics
+ location ~* ^/metrics/?$ {
+ return 404 'Not found';
+ }
+
+ # block external access to all health checks /health_check, /health_check/full, etc
+ location ~* ^/health_check {
+ return 404 'Not found';
+ }
+
# Load any extra configuration for this vhost
include /etc/nginx/vhost-extras/overleaf/*.conf;
}

View file

@ -0,0 +1,30 @@
diff --git a/services/web/locales/en.json b/services/web/locales/en.json
index a953a01a1d7..13e20b37279 100644
--- a/services/web/locales/en.json
+++ b/services/web/locales/en.json
@@ -519,7 +519,6 @@
"editor_disconected_click_to_reconnect": "Editor disconnected, click anywhere to reconnect.",
"editor_limit_exceeded_in_this_project": "Too many editors in this project",
"editor_only_hide_pdf": "Editor only <0>(hide PDF)</0>",
- "editor_resources": "Editor Resources",
"editor_theme": "Editor theme",
"educational_discount_applied": "40% educational discount applied!",
"educational_discount_available_for_groups_of_ten_or_more": "The educational discount is available for groups of 10 or more",
diff --git a/services/web/modules/launchpad/app/views/launchpad.pug b/services/web/modules/launchpad/app/views/launchpad.pug
index c478fe7b649..28d3ff8fc83 100644
--- a/services/web/modules/launchpad/app/views/launchpad.pug
+++ b/services/web/modules/launchpad/app/views/launchpad.pug
@@ -166,13 +166,6 @@ block content
h2 #{translate('status_checks')}
- <!-- ide js -->
- .row.row-spaced-small
- .col-sm-5
- | #{translate('editor_resources')}
- .col-sm-7
- +launchpad-check('ide')
-
<!-- websocket -->
.row.row-spaced-small
.col-sm-5

View file

@ -0,0 +1,59 @@
diff --git a/services/web/app/src/infrastructure/CSP.js b/services/web/app/src/infrastructure/CSP.js
index 28f4f380d3d..abc11c59a48 100644
--- a/services/web/app/src/infrastructure/CSP.js
+++ b/services/web/app/src/infrastructure/CSP.js
@@ -6,6 +6,7 @@ module.exports = function ({
reportPercentage,
reportOnly = false,
exclude = [],
+ viewDirectives = {},
}) {
const header = reportOnly
? 'Content-Security-Policy-Report-Only'
@@ -33,7 +34,12 @@ module.exports = function ({
res.locals.scriptNonce = scriptNonce
- const policy = buildViewPolicy(scriptNonce, reportPercentage, reportUri)
+ const policy = buildViewPolicy(
+ scriptNonce,
+ reportPercentage,
+ reportUri,
+ viewDirectives[view]
+ )
// Note: https://csp-evaluator.withgoogle.com/ is useful for checking the policy
@@ -68,11 +74,17 @@ const buildDefaultPolicy = (reportUri, styleSrc) => {
return directives.join('; ')
}
-const buildViewPolicy = (scriptNonce, reportPercentage, reportUri) => {
+const buildViewPolicy = (
+ scriptNonce,
+ reportPercentage,
+ reportUri,
+ viewDirectives
+) => {
const directives = [
`script-src 'nonce-${scriptNonce}' 'unsafe-inline' 'strict-dynamic' https: 'report-sample'`, // only allow scripts from certain sources
`object-src 'none'`, // forbid loading an "object" element
`base-uri 'none'`, // forbid setting a "base" element
+ ...(viewDirectives ?? []),
]
if (reportUri) {
diff --git a/services/web/config/settings.defaults.js b/services/web/config/settings.defaults.js
index cad13ab8156..ab738babdcd 100644
--- a/services/web/config/settings.defaults.js
+++ b/services/web/config/settings.defaults.js
@@ -911,6 +911,9 @@ module.exports = {
reportPercentage: parseFloat(process.env.CSP_REPORT_PERCENTAGE) || 0,
reportUri: process.env.CSP_REPORT_URI,
exclude: [],
+ viewDirectives: {
+ 'app/views/project/ide-react': [`img-src 'self' data: blob:`],
+ },
},
unsupportedBrowsers: {

View file

@ -0,0 +1,46 @@
diff --git a/services/web/app/src/Features/HealthCheck/HealthCheckController.js b/services/web/app/src/Features/HealthCheck/HealthCheckController.js
index 278f04bb767..ff074cfa816 100644
--- a/services/web/app/src/Features/HealthCheck/HealthCheckController.js
+++ b/services/web/app/src/Features/HealthCheck/HealthCheckController.js
@@ -45,6 +45,10 @@ module.exports = {
logger.err({ err }, 'failed api redis health check')
return res.sendStatus(500)
}
+ if (!settings.smokeTest.userId) {
+ logger.err({}, 'smokeTest.userId is undefined in health check')
+ return res.sendStatus(404)
+ }
UserGetter.getUserEmail(settings.smokeTest.userId, (err, email) => {
if (err) {
logger.err({ err }, 'failed api mongo health check')
diff --git a/services/web/app/src/infrastructure/ExpressLocals.js b/services/web/app/src/infrastructure/ExpressLocals.js
index 5f14977d3a3..2e9ed4f1ebb 100644
--- a/services/web/app/src/infrastructure/ExpressLocals.js
+++ b/services/web/app/src/infrastructure/ExpressLocals.js
@@ -11,6 +11,7 @@ const Features = require('./Features')
const SessionManager = require('../Features/Authentication/SessionManager')
const PackageVersions = require('./PackageVersions')
const Modules = require('./Modules')
+const Errors = require('../Features/Errors/Errors')
const {
canRedirectToAdminDomain,
hasAdminAccess,
@@ -236,10 +237,14 @@ module.exports = function (webRouter, privateApiRouter, publicApiRouter) {
// Don't include the query string parameters, otherwise Google
// treats ?nocdn=true as the canonical version
- const parsedOriginalUrl = new URL(req.originalUrl, Settings.siteUrl)
- res.locals.currentUrl = parsedOriginalUrl.pathname
- res.locals.currentUrlWithQueryParams =
- parsedOriginalUrl.pathname + parsedOriginalUrl.search
+ try {
+ const parsedOriginalUrl = new URL(req.originalUrl, Settings.siteUrl)
+ res.locals.currentUrl = parsedOriginalUrl.pathname
+ res.locals.currentUrlWithQueryParams =
+ parsedOriginalUrl.pathname + parsedOriginalUrl.search
+ } catch (err) {
+ return next(new Errors.InvalidError())
+ }
res.locals.capitalize = function (string) {
if (string.length === 0) {
return ''

View file

@ -0,0 +1,26 @@
diff --git a/services/web/app/src/Features/Email/EmailBuilder.js b/services/web/app/src/Features/Email/EmailBuilder.js
index 46d014a8e14..d839d67f634 100644
--- a/services/web/app/src/Features/Email/EmailBuilder.js
+++ b/services/web/app/src/Features/Email/EmailBuilder.js
@@ -234,7 +234,7 @@ templates.confirmEmail = ctaTemplate({
},
secondaryMessage() {
return [
- 'If you did not request this, please let us know at <a href="mailto:support@overleaf.com">support@overleaf.com</a>.',
+ `If you did not request this, please let us know at <a href="mailto:${settings.adminEmail}">${settings.adminEmail}</a>.`,
`If you have any questions or trouble confirming your email address, please get in touch with our support team at ${settings.adminEmail}.`,
]
},
diff --git a/services/web/app/src/Features/User/UserRegistrationHandler.js b/services/web/app/src/Features/User/UserRegistrationHandler.js
index 2802fdc81c5..02c52f73fd2 100644
--- a/services/web/app/src/Features/User/UserRegistrationHandler.js
+++ b/services/web/app/src/Features/User/UserRegistrationHandler.js
@@ -113,7 +113,7 @@ const UserRegistrationHandler = {
const setNewPasswordUrl = `${settings.siteUrl}/user/activate?token=${token}&user_id=${user._id}`
- EmailHandler.promises
+ await EmailHandler.promises
.sendEmail('registered', {
to: user.email,
setNewPasswordUrl,

View file

@ -67,6 +67,16 @@ server {
proxy_http_version 1.1;
}
# block external access to metrics
location ~* ^/metrics/?$ {
return 404 'Not found';
}
# block external access to all health checks /health_check, /health_check/full, etc
location ~* ^/health_check {
return 404 'Not found';
}
# Load any extra configuration for this vhost
include /etc/nginx/vhost-extras/overleaf/*.conf;
}