From 6fa3103126d1ff347da4c9198ddf2ac8cf95cf0b 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] 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 rel=noreferrer: 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: * a rel=noopener: 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(''); }