From 4489b5a21aa7550d1bfeee1b4f3960ebc4698cb7 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 28 Dec 2019 20:05:55 +0000 Subject: [PATCH 1/3] Escape HTML in og:description and render any html &-encoded entities --- src/components/views/rooms/LinkPreviewWidget.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/LinkPreviewWidget.js b/src/components/views/rooms/LinkPreviewWidget.js index ee63cd1bb7..06c0201af8 100644 --- a/src/components/views/rooms/LinkPreviewWidget.js +++ b/src/components/views/rooms/LinkPreviewWidget.js @@ -128,15 +128,15 @@ module.exports = createReactClass({ } const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + // Escape to prevent any HTML injections, we can't replace & as the description may contain & encoded html entities + const safeDescription = (p["og:description"] || "").replace("<", "<").replace(">", ">"); return (
{ img }
{ p["og:title"] }
{ p["og:site_name"] ? (" - " + p["og:site_name"]) : null }
-
- { p["og:description"] } -
+
Date: Sun, 5 Jan 2020 22:22:09 +0000 Subject: [PATCH 2/3] Use html-entities instead Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 3 ++- src/components/views/rooms/LinkPreviewWidget.js | 10 ++++++---- yarn.lock | 5 +++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 7ef14e6635..7e2c242b3a 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,6 @@ "file-saver": "^1.3.3", "filesize": "3.5.6", "flux": "2.1.1", - "react-focus-lock": "^2.2.1", "focus-visible": "^5.0.2", "fuse.js": "^2.2.0", "gemini-scrollbar": "github:matrix-org/gemini-scrollbar#91e1e566", @@ -82,6 +81,7 @@ "glob": "^5.0.14", "glob-to-regexp": "^0.4.1", "highlight.js": "^9.15.8", + "html-entities": "^1.2.1", "is-ip": "^2.0.0", "isomorphic-fetch": "^2.2.1", "linkifyjs": "^2.1.6", @@ -99,6 +99,7 @@ "react-addons-css-transition-group": "15.6.2", "react-beautiful-dnd": "^4.0.1", "react-dom": "^16.9.0", + "react-focus-lock": "^2.2.1", "react-gemini-scrollbar": "github:matrix-org/react-gemini-scrollbar#9cf17f63b7c0b0ec5f31df27da0f82f7238dc594", "resize-observer-polyfill": "^1.5.0", "sanitize-html": "^1.18.4", diff --git a/src/components/views/rooms/LinkPreviewWidget.js b/src/components/views/rooms/LinkPreviewWidget.js index 06c0201af8..4822848233 100644 --- a/src/components/views/rooms/LinkPreviewWidget.js +++ b/src/components/views/rooms/LinkPreviewWidget.js @@ -18,7 +18,9 @@ limitations under the License. import React, {createRef} from 'react'; import PropTypes from 'prop-types'; import createReactClass from 'create-react-class'; -import { linkifyElement } from '../../../HtmlUtils'; +import { AllHtmlEntities } from 'html-entities'; + +import {linkifyElement} from '../../../HtmlUtils'; import SettingsStore from "../../../settings/SettingsStore"; import { _t } from "../../../languageHandler"; @@ -128,15 +130,15 @@ module.exports = createReactClass({ } const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); - // Escape to prevent any HTML injections, we can't replace & as the description may contain & encoded html entities - const safeDescription = (p["og:description"] || "").replace("<", "<").replace(">", ">"); return (
{ img }
{ p["og:site_name"] ? (" - " + p["og:site_name"]) : null }
-
+
+ { AllHtmlEntities.decode(p["og:description"] || "") } +
Date: Mon, 6 Jan 2020 00:18:24 +0000 Subject: [PATCH 3/3] Add comment and delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/LinkPreviewWidget.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/LinkPreviewWidget.js b/src/components/views/rooms/LinkPreviewWidget.js index 4822848233..3b5545e0e0 100644 --- a/src/components/views/rooms/LinkPreviewWidget.js +++ b/src/components/views/rooms/LinkPreviewWidget.js @@ -19,7 +19,6 @@ import React, {createRef} from 'react'; import PropTypes from 'prop-types'; import createReactClass from 'create-react-class'; import { AllHtmlEntities } from 'html-entities'; - import {linkifyElement} from '../../../HtmlUtils'; import SettingsStore from "../../../settings/SettingsStore"; import { _t } from "../../../languageHandler"; @@ -129,6 +128,10 @@ module.exports = createReactClass({
; } + // The description includes &-encoded HTML entities, we decode those as React treats the thing as an + // opaque string. This does not allow any HTML to be injected into the DOM. + const description = AllHtmlEntities.decode(p["og:description"] || ""); + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); return (
@@ -137,7 +140,7 @@ module.exports = createReactClass({
{ p["og:site_name"] ? (" - " + p["og:site_name"]) : null }
- { AllHtmlEntities.decode(p["og:description"] || "") } + { description }