mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
[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:
parent
c117483761
commit
e08057828f
11 changed files with 344 additions and 0 deletions
11
server-ce/hotfix/4.2.8/Dockerfile
Normal file
11
server-ce/hotfix/4.2.8/Dockerfile
Normal 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
|
19
server-ce/hotfix/4.2.8/is_19575.patch
Normal file
19
server-ce/hotfix/4.2.8/is_19575.patch
Normal 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;
|
||||||
|
}
|
58
server-ce/hotfix/4.2.8/pr_19550.patch
Normal file
58
server-ce/hotfix/4.2.8/pr_19550.patch
Normal 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: {
|
||||||
|
|
46
server-ce/hotfix/4.2.8/pr_19612.patch
Normal file
46
server-ce/hotfix/4.2.8/pr_19612.patch
Normal 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 ''
|
20
server-ce/hotfix/5.1.1/Dockerfile
Normal file
20
server-ce/hotfix/5.1.1/Dockerfile
Normal 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
|
||||||
|
|
19
server-ce/hotfix/5.1.1/is_19575.patch
Normal file
19
server-ce/hotfix/5.1.1/is_19575.patch
Normal 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;
|
||||||
|
}
|
30
server-ce/hotfix/5.1.1/pr_19543.patch
Normal file
30
server-ce/hotfix/5.1.1/pr_19543.patch
Normal 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
|
59
server-ce/hotfix/5.1.1/pr_19550.patch
Normal file
59
server-ce/hotfix/5.1.1/pr_19550.patch
Normal 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: {
|
46
server-ce/hotfix/5.1.1/pr_19612.patch
Normal file
46
server-ce/hotfix/5.1.1/pr_19612.patch
Normal 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 ''
|
26
server-ce/hotfix/5.1.1/pr_19676.patch
Normal file
26
server-ce/hotfix/5.1.1/pr_19676.patch
Normal 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,
|
|
@ -67,6 +67,16 @@ server {
|
||||||
proxy_http_version 1.1;
|
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
|
# Load any extra configuration for this vhost
|
||||||
include /etc/nginx/vhost-extras/overleaf/*.conf;
|
include /etc/nginx/vhost-extras/overleaf/*.conf;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue