From 386c65c61d788614c6a51002c6e34a8367a37858 Mon Sep 17 00:00:00 2001
From: ahmadine <54514036+ahmadine@users.noreply.github.com>
Date: Sat, 23 Nov 2019 08:18:07 +0100
Subject: [PATCH] referer: work towards the greatest level of referrer security
Pull request with discussion: https://github.com/ether/etherpad-lite/pull/3636
What's already there:
* `meta name=referrer`: already done in 1.6.1:
https://github.com/ether/etherpad-lite/pull/3044
https://caniuse.com/#feat=referrer-policy
https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-delivery-meta
(Chrome>=78, Firefox>=70, Safari>=13, Opera>=64, ~IE[1], ~Edge[1])
The previous two commits (by @joelpurra) I backported in this batch:
* ``: a pull request denied before:
https://github.com/ether/etherpad-lite/pull/2498
https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer
https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types
(Firefox>=37, I can't find more info about support)
This commit adds the following:
* ``: fixing a not-so-well-known way to extract referer
https://html.spec.whatwg.org/multipage/links.html#link-type-noopener
(Chrome>=49, Firefox>=52, Safari>=10.1, Opera>=36, !IE, !Edge)
* `Referrer-Policy: same-origin`: the last bastion of referrer security
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
(Chrome>=61, Firefox>=52, Safari>=11.1, Opera>=48, !IE, !Edge)
meta name=referrer wasn't enough. I happened to leak a few referrers with my
Firefox browser, though for some browsers it could have been enough.
[1] IE>=11, Edge>=18 use a different syntax for meta name=referrer, making it
most probably incompatible (but I may be wrong on that, they may support
both, but I have no way to test it currently). The next Edge release will be
based on Chromium, so for that the Chrome version applies.
---
CHANGELOG.md | 3 +++
src/node/hooks/express.js | 9 +++++++++
src/node/utils/ExportHtml.js | 8 ++++++--
src/static/js/domline.js | 8 ++++++--
src/static/js/pad_utils.js | 8 ++++++--
5 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cf7abc58779e..6a19c1fb50f9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+# 1.8
+* SECURITY: improve referrer policy so that Etherpad addresses aren't leaked when links are clicked (see https://github.com/ether/etherpad-lite/pull/3636)
+
# 1.8-beta.1
* FEATURE: code was migrated to `async`/`await`, getting rid of a lot of callbacks (see https://github.com/ether/etherpad-lite/issues/3540)
* FEATURE: support configuration via environment variables
diff --git a/src/node/hooks/express.js b/src/node/hooks/express.js
index 702214ec85aa..6394ffbfc15f 100644
--- a/src/node/hooks/express.js
+++ b/src/node/hooks/express.js
@@ -76,6 +76,15 @@ exports.restartServer = function () {
// https://github.com/ether/etherpad-lite/issues/2547
res.header("X-UA-Compatible", "IE=Edge,chrome=1");
+ // Enable a strong referrer policy. Same-origin won't drop Referers when
+ // loading local resources, but it will drop them when loading foreign resources.
+ // It's still a last bastion of referrer security. External URLs should be
+ // already marked with rel="noreferer" and user-generated content pages are already
+ // marked with
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
+ // https://github.com/ether/etherpad-lite/pull/3636
+ res.header("Referrer-Policy", "same-origin");
+
// send git version in the Server response header if exposeVersion is true.
if (settings.exposeVersion) {
res.header("Server", serverName);
diff --git a/src/node/utils/ExportHtml.js b/src/node/utils/ExportHtml.js
index 086ec89e9eec..aa7b0abcc4c1 100644
--- a/src/node/utils/ExportHtml.js
+++ b/src/node/utils/ExportHtml.js
@@ -287,8 +287,12 @@ function getHTMLFromAtext(pad, atext, authorColors)
processNextChars(startIndex - idx);
// Using rel="noreferrer" stops leaking the URL/location of the exported HTML when clicking links in the document.
// Not all browsers understand this attribute, but it's part of the HTML5 standard.
- // http://www.w3.org/TR/html5/links.html#link-type-noreferrer
- assem.append('');
+ // https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer
+ // Additionally, we do rel="noopener" to ensure a higher level of referrer security.
+ // https://html.spec.whatwg.org/multipage/links.html#link-type-noopener
+ // https://mathiasbynens.github.io/rel-noopener/
+ // https://github.com/ether/etherpad-lite/pull/3636
+ assem.append('');
processNextChars(urlLength);
assem.append('');
});
diff --git a/src/static/js/domline.js b/src/static/js/domline.js
index 7904029bddd8..0ae46b29946d 100644
--- a/src/static/js/domline.js
+++ b/src/static/js/domline.js
@@ -200,8 +200,12 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
}
// Using rel="noreferrer" stops leaking the URL/location of the pad when clicking links in the document.
// Not all browsers understand this attribute, but it's part of the HTML5 standard.
- // http://www.w3.org/TR/html5/links.html#link-type-noreferrer
- extraOpenTags = extraOpenTags + '';
+ // https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer
+ // Additionally, we do rel="noopener" to ensure a higher level of referrer security.
+ // https://html.spec.whatwg.org/multipage/links.html#link-type-noopener
+ // https://mathiasbynens.github.io/rel-noopener/
+ // https://github.com/ether/etherpad-lite/pull/3636
+ extraOpenTags = extraOpenTags + '';
extraCloseTags = '' + extraCloseTags;
}
if (simpleTags)
diff --git a/src/static/js/pad_utils.js b/src/static/js/pad_utils.js
index 855dd82b12b1..d42cbb022425 100644
--- a/src/static/js/pad_utils.js
+++ b/src/static/js/pad_utils.js
@@ -225,8 +225,12 @@ var padutils = {
advanceTo(startIndex);
// Using rel="noreferrer" stops leaking the URL/location of the pad when clicking links in the document.
// Not all browsers understand this attribute, but it's part of the HTML5 standard.
- // http://www.w3.org/TR/html5/links.html#link-type-noreferrer
- pieces.push('');
+ // https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer
+ // Additionally, we do rel="noopener" to ensure a higher level of referrer security.
+ // https://html.spec.whatwg.org/multipage/links.html#link-type-noopener
+ // https://mathiasbynens.github.io/rel-noopener/
+ // https://github.com/ether/etherpad-lite/pull/3636
+ pieces.push('');
advanceTo(startIndex + href.length);
pieces.push('');
}