From 5ea24f650b459ec678f48e6431a6838dd1ff4c78 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 22 Mar 2018 12:01:16 +0900 Subject: [PATCH] Make sanitization configurable --- browser/components/MarkdownEditor.js | 1 + browser/components/MarkdownPreview.js | 9 +- browser/components/MarkdownSplitEditor.js | 1 + browser/lib/markdown.js | 86 +++++++++++-------- browser/main/lib/ConfigManager.js | 3 +- browser/main/modals/PreferencesModal/UiTab.js | 20 ++++- locales/da.json | 6 +- locales/de.json | 6 +- locales/en.json | 6 +- locales/es.json | 6 +- locales/fr.json | 10 ++- locales/ja.json | 6 +- locales/ko.json | 6 +- locales/no.json | 6 +- locales/pl.json | 6 +- locales/pt.json | 6 +- locales/sq.json | 6 +- locales/zh-CN.json | 6 +- locales/zh-TW.json | 6 +- 19 files changed, 145 insertions(+), 57 deletions(-) diff --git a/browser/components/MarkdownEditor.js b/browser/components/MarkdownEditor.js index d0e2f505..98c1942b 100644 --- a/browser/components/MarkdownEditor.js +++ b/browser/components/MarkdownEditor.js @@ -280,6 +280,7 @@ class MarkdownEditor extends React.Component { indentSize={editorIndentSize} scrollPastEnd={config.preview.scrollPastEnd} smartQuotes={config.preview.smartQuotes} + sanitize={config.preview.sanitize} ref='preview' onContextMenu={(e) => this.handleContextMenu(e)} onDoubleClick={(e) => this.handleDoubleClick(e)} diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index e4298a71..bd5d3939 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -135,8 +135,11 @@ export default class MarkdownPreview extends React.Component { } initMarkdown () { - const { smartQuotes } = this.props - this.markdown = new Markdown({ typographer: smartQuotes }) + const { smartQuotes, sanitize } = this.props + this.markdown = new Markdown({ + typographer: smartQuotes, + sanitize + }) } handlePreviewAnchorClick (e) { @@ -318,7 +321,7 @@ export default class MarkdownPreview extends React.Component { componentDidUpdate (prevProps) { if (prevProps.value !== this.props.value) this.rewriteIframe() - if (prevProps.smartQuotes !== this.props.smartQuotes) { + if (prevProps.smartQuotes !== this.props.smartQuotes || prevProps.sanitize !== this.props.sanitize) { this.initMarkdown() this.rewriteIframe() } diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index 0aa2d16c..945f5d62 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -128,6 +128,7 @@ class MarkdownSplitEditor extends React.Component { lineNumber={config.preview.lineNumber} scrollPastEnd={config.preview.scrollPastEnd} smartQuotes={config.preview.smartQuotes} + sanitize={config.preview.sanitize} ref='preview' tabInde='0' value={value} diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index ee38c27d..6f1f2f00 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -45,52 +45,62 @@ class Markdown { '' + str + '' - } + }, + sanitize: 'STRICT' } const updatedOptions = Object.assign(defaultOptions, options) this.md = markdownit(updatedOptions) - // Sanitize use rinput before other plugins - this.md.use(sanitize, { - allowedTags: ['iframe', 'input', 'b', + if (updatedOptions.sanitize !== 'NONE') { + const allowedTags = ['iframe', 'input', 'b', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'br', 'b', 'i', 'strong', 'em', 'a', 'pre', 'code', 'img', 'tt', 'div', 'ins', 'del', 'sup', 'sub', 'p', 'ol', 'ul', 'table', 'thead', 'tbody', 'tfoot', 'blockquote', 'dl', 'dt', 'dd', 'kbd', 'q', 'samp', 'var', 'hr', 'ruby', 'rt', 'rp', 'li', 'tr', 'td', 'th', 's', 'strike', 'summary', 'details' - ], - allowedAttributes: { - '*': [ - 'style', - 'abbr', 'accept', 'accept-charset', - 'accesskey', 'action', 'align', 'alt', 'axis', - 'border', 'cellpadding', 'cellspacing', 'char', - 'charoff', 'charset', 'checked', - 'clear', 'cols', 'colspan', 'color', - 'compact', 'coords', 'datetime', 'dir', - 'disabled', 'enctype', 'for', 'frame', - 'headers', 'height', 'hreflang', - 'hspace', 'ismap', 'label', 'lang', - 'maxlength', 'media', 'method', - 'multiple', 'name', 'nohref', 'noshade', - 'nowrap', 'open', 'prompt', 'readonly', 'rel', 'rev', - 'rows', 'rowspan', 'rules', 'scope', - 'selected', 'shape', 'size', 'span', - 'start', 'summary', 'tabindex', 'target', - 'title', 'type', 'usemap', 'valign', 'value', - 'vspace', 'width', 'itemprop' - ], - 'a': ['href'], - 'div': ['itemscope', 'itemtype'], - 'blockquote': ['cite'], - 'del': ['cite'], - 'ins': ['cite'], - 'q': ['cite'], - 'img': ['src', 'width', 'height'], - 'iframe': ['src', 'width', 'height', 'frameborder', 'allowfullscreen'], - 'input': ['type', 'id', 'checked'] - }, - allowedIframeHostnames: ['www.youtube.com'] - }) + ] + const allowedAttributes = [ + 'abbr', 'accept', 'accept-charset', + 'accesskey', 'action', 'align', 'alt', 'axis', + 'border', 'cellpadding', 'cellspacing', 'char', + 'charoff', 'charset', 'checked', + 'clear', 'cols', 'colspan', 'color', + 'compact', 'coords', 'datetime', 'dir', + 'disabled', 'enctype', 'for', 'frame', + 'headers', 'height', 'hreflang', + 'hspace', 'ismap', 'label', 'lang', + 'maxlength', 'media', 'method', + 'multiple', 'name', 'nohref', 'noshade', + 'nowrap', 'open', 'prompt', 'readonly', 'rel', 'rev', + 'rows', 'rowspan', 'rules', 'scope', + 'selected', 'shape', 'size', 'span', + 'start', 'summary', 'tabindex', 'target', + 'title', 'type', 'usemap', 'valign', 'value', + 'vspace', 'width', 'itemprop' + ] + + if (updatedOptions.sanitize === 'ALLOW_STYLES') { + allowedTags.push('style') + allowedAttributes.push('style') + } + + // Sanitize use rinput before other plugins + this.md.use(sanitize, { + allowedTags, + allowedAttributes: { + '*': allowedAttributes, + 'a': ['href'], + 'div': ['itemscope', 'itemtype'], + 'blockquote': ['cite'], + 'del': ['cite'], + 'ins': ['cite'], + 'q': ['cite'], + 'img': ['src', 'width', 'height'], + 'iframe': ['src', 'width', 'height', 'frameborder', 'allowfullscreen'], + 'input': ['type', 'id', 'checked'] + }, + allowedIframeHostnames: ['www.youtube.com'] + }) + } this.md.use(emoji, { shortcuts: {} diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index 40b89198..ff220348 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -51,7 +51,8 @@ export const DEFAULT_CONFIG = { latexBlockOpen: '$$', latexBlockClose: '$$', scrollPastEnd: false, - smartQuotes: true + smartQuotes: true, + sanitize: 'STRICT' // 'STRICT', 'ALLOW_STYLES', 'NONE' }, blog: { type: 'wordpress', // Available value: wordpress, add more types in the future plz diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index 81e29746..708dd82a 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -91,7 +91,8 @@ class UiTab extends React.Component { latexBlockOpen: this.refs.previewLatexBlockOpen.value, latexBlockClose: this.refs.previewLatexBlockClose.value, scrollPastEnd: this.refs.previewScrollPastEnd.checked, - smartQuotes: this.refs.previewSmartQuotes.checked + smartQuotes: this.refs.previewSmartQuotes.checked, + sanitize: this.refs.previewSanitize.value } } @@ -441,6 +442,23 @@ class UiTab extends React.Component { Enable smart quotes + +
+
+ {i18n.__('Sanitization')} +
+
+ +
+
{i18n.__('LaTeX Inline Open Delimiter')} diff --git a/locales/da.json b/locales/da.json index e54245f9..be3c0491 100644 --- a/locales/da.json +++ b/locales/da.json @@ -141,5 +141,9 @@ "Portuguese": "Portuguese", "Spanish": "Spanish", "You have to save!": "You have to save!", - "Russian": "Russian" + "Russian": "Russian", + "Sanitization": "Sanitization", + "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", + "Allow styles": "Allow styles", + "Allow dangerous html tags": "Allow dangerous html tags" } \ No newline at end of file diff --git a/locales/de.json b/locales/de.json index 9c36871c..027310e1 100644 --- a/locales/de.json +++ b/locales/de.json @@ -143,5 +143,9 @@ "Successfully applied!": "Erfolgreich angewendet!", "UserName": "UserName", "Password": "Password", - "Russian": "Russian" + "Russian": "Russian", + "Sanitization": "Sanitization", + "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", + "Allow styles": "Allow styles", + "Allow dangerous html tags": "Allow dangerous html tags" } \ No newline at end of file diff --git a/locales/en.json b/locales/en.json index db13da16..182f5a47 100644 --- a/locales/en.json +++ b/locales/en.json @@ -144,5 +144,9 @@ "UserName": "UserName", "Password": "Password", "Russian": "Russian", - "Command(⌘)": "Command(⌘)" + "Command(⌘)": "Command(⌘)", + "Sanitization": "Sanitization", + "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", + "Allow styles": "Allow styles", + "Allow dangerous html tags": "Allow dangerous html tags" } \ No newline at end of file diff --git a/locales/es.json b/locales/es.json index e54245f9..be3c0491 100644 --- a/locales/es.json +++ b/locales/es.json @@ -141,5 +141,9 @@ "Portuguese": "Portuguese", "Spanish": "Spanish", "You have to save!": "You have to save!", - "Russian": "Russian" + "Russian": "Russian", + "Sanitization": "Sanitization", + "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", + "Allow styles": "Allow styles", + "Allow dangerous html tags": "Allow dangerous html tags" } \ No newline at end of file diff --git a/locales/fr.json b/locales/fr.json index 6f664280..fcc0fc6a 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -139,5 +139,11 @@ "Polish": "Polonais", "Portuguese": "Portugais", "Spanish": "Espagnol", - "You have to save!": "Il faut sauvegarder !" - } \ No newline at end of file + "You have to save!": "Il faut sauvegarder !", + "Russian": "Russian", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Sanitization": "Sanitization", + "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", + "Allow styles": "Allow styles", + "Allow dangerous html tags": "Allow dangerous html tags" +} \ No newline at end of file diff --git a/locales/ja.json b/locales/ja.json index e54245f9..be3c0491 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -141,5 +141,9 @@ "Portuguese": "Portuguese", "Spanish": "Spanish", "You have to save!": "You have to save!", - "Russian": "Russian" + "Russian": "Russian", + "Sanitization": "Sanitization", + "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", + "Allow styles": "Allow styles", + "Allow dangerous html tags": "Allow dangerous html tags" } \ No newline at end of file diff --git a/locales/ko.json b/locales/ko.json index 4b85c0e3..8a5c6f61 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -148,5 +148,9 @@ "UserName": "유저명", "Password": "패스워드", "Storage": "저장소", - "Hotkeys": "단축키" + "Hotkeys": "단축키", + "Sanitization": "허용 태그 범위", + "Only allow secure html tags (recommended)": "안전한 HTML 태그만 허용 (추천)", + "Allow styles": "style 태그, 속성까지 허용", + "Allow dangerous html tags": "모든 위험한 태그 허용" } \ No newline at end of file diff --git a/locales/no.json b/locales/no.json index e54245f9..be3c0491 100644 --- a/locales/no.json +++ b/locales/no.json @@ -141,5 +141,9 @@ "Portuguese": "Portuguese", "Spanish": "Spanish", "You have to save!": "You have to save!", - "Russian": "Russian" + "Russian": "Russian", + "Sanitization": "Sanitization", + "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", + "Allow styles": "Allow styles", + "Allow dangerous html tags": "Allow dangerous html tags" } \ No newline at end of file diff --git a/locales/pl.json b/locales/pl.json index e54245f9..be3c0491 100644 --- a/locales/pl.json +++ b/locales/pl.json @@ -141,5 +141,9 @@ "Portuguese": "Portuguese", "Spanish": "Spanish", "You have to save!": "You have to save!", - "Russian": "Russian" + "Russian": "Russian", + "Sanitization": "Sanitization", + "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", + "Allow styles": "Allow styles", + "Allow dangerous html tags": "Allow dangerous html tags" } \ No newline at end of file diff --git a/locales/pt.json b/locales/pt.json index e54245f9..be3c0491 100644 --- a/locales/pt.json +++ b/locales/pt.json @@ -141,5 +141,9 @@ "Portuguese": "Portuguese", "Spanish": "Spanish", "You have to save!": "You have to save!", - "Russian": "Russian" + "Russian": "Russian", + "Sanitization": "Sanitization", + "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", + "Allow styles": "Allow styles", + "Allow dangerous html tags": "Allow dangerous html tags" } \ No newline at end of file diff --git a/locales/sq.json b/locales/sq.json index e54245f9..be3c0491 100644 --- a/locales/sq.json +++ b/locales/sq.json @@ -141,5 +141,9 @@ "Portuguese": "Portuguese", "Spanish": "Spanish", "You have to save!": "You have to save!", - "Russian": "Russian" + "Russian": "Russian", + "Sanitization": "Sanitization", + "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", + "Allow styles": "Allow styles", + "Allow dangerous html tags": "Allow dangerous html tags" } \ No newline at end of file diff --git a/locales/zh-CN.json b/locales/zh-CN.json index e54245f9..be3c0491 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -141,5 +141,9 @@ "Portuguese": "Portuguese", "Spanish": "Spanish", "You have to save!": "You have to save!", - "Russian": "Russian" + "Russian": "Russian", + "Sanitization": "Sanitization", + "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", + "Allow styles": "Allow styles", + "Allow dangerous html tags": "Allow dangerous html tags" } \ No newline at end of file diff --git a/locales/zh-TW.json b/locales/zh-TW.json index e54245f9..be3c0491 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -141,5 +141,9 @@ "Portuguese": "Portuguese", "Spanish": "Spanish", "You have to save!": "You have to save!", - "Russian": "Russian" + "Russian": "Russian", + "Sanitization": "Sanitization", + "Only allow secure html tags (recommended)": "Only allow secure html tags (recommended)", + "Allow styles": "Allow styles", + "Allow dangerous html tags": "Allow dangerous html tags" } \ No newline at end of file