From 6b4d7923dbd990cf378914a17c3798bf265a19d8 Mon Sep 17 00:00:00 2001 From: KT Date: Thu, 27 Jun 2019 01:07:13 +0200 Subject: [PATCH 01/11] add deprecation warning for sanitize option --- lib/marked.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/marked.js b/lib/marked.js index 86286794e5..bd69ca29d0 100644 --- a/lib/marked.js +++ b/lib/marked.js @@ -1536,6 +1536,12 @@ function findClosingBracket(str, b) { return -1; } +function checkSanitizeDeprecation(opt) { + if (opt && opt.sanitize && !opt.silent) { + console.warn("marked(): sanitize and sanitizer parameters are deprecated since version 0.6.3 and will be removed from the next major version. Please use an external library, e.g. DOMPurify for your sanitization needs."); + } +} + /** * Marked */ @@ -1557,6 +1563,7 @@ function marked(src, opt, callback) { } opt = merge({}, marked.defaults, opt || {}); + checkSanitizeDeprecation(opt); var highlight = opt.highlight, tokens, @@ -1621,6 +1628,7 @@ function marked(src, opt, callback) { } try { if (opt) opt = merge({}, marked.defaults, opt); + checkSanitizeDeprecation(opt); return Parser.parse(Lexer.lex(src, opt), opt); } catch (e) { e.message += '\nPlease report this to https://github.com/markedjs/marked.'; From 08389dba3c50c4c6f41625a680df15cb05cc3fd0 Mon Sep 17 00:00:00 2001 From: KT Date: Thu, 27 Jun 2019 01:08:58 +0200 Subject: [PATCH 02/11] harden sanitization --- lib/marked.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/marked.js b/lib/marked.js index bd69ca29d0..240c7c16e6 100644 --- a/lib/marked.js +++ b/lib/marked.js @@ -434,7 +434,7 @@ Lexer.prototype.token = function(src, top) { : 'html', pre: !this.options.sanitizer && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), - text: cap[0] + text: this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0])) : cap[0] }); continue; } @@ -847,7 +847,7 @@ InlineLexer.prototype.output = function(src) { if (cap = this.rules.text.exec(src)) { src = src.substring(cap[0].length); if (this.inRawBlock) { - out += this.renderer.text(cap[0]); + out += this.renderer.text(this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0])) : cap[0]); } else { out += this.renderer.text(escape(this.smartypants(cap[0]))); } From 506704a5fed4399281eceea2951e484e4d143c40 Mon Sep 17 00:00:00 2001 From: KT Date: Thu, 27 Jun 2019 01:09:34 +0200 Subject: [PATCH 03/11] add test cases for sanitization hardening --- test/specs/run-spec.js | 3 +++ test/specs/security/sanitizer_bypass.html | 6 ++++++ test/specs/security/sanitizer_bypass.md | 9 +++++++++ test/specs/security/sanitizer_bypass_remove_generic.html | 2 ++ test/specs/security/sanitizer_bypass_remove_generic.md | 6 ++++++ test/specs/security/sanitizer_bypass_remove_script.html | 1 + test/specs/security/sanitizer_bypass_remove_script.md | 5 +++++ test/specs/security/sanitizer_bypass_remove_tag.html | 1 + test/specs/security/sanitizer_bypass_remove_tag.md | 5 +++++ 9 files changed, 38 insertions(+) create mode 100644 test/specs/security/sanitizer_bypass.html create mode 100644 test/specs/security/sanitizer_bypass.md create mode 100644 test/specs/security/sanitizer_bypass_remove_generic.html create mode 100644 test/specs/security/sanitizer_bypass_remove_generic.md create mode 100644 test/specs/security/sanitizer_bypass_remove_script.html create mode 100644 test/specs/security/sanitizer_bypass_remove_script.md create mode 100644 test/specs/security/sanitizer_bypass_remove_tag.html create mode 100644 test/specs/security/sanitizer_bypass_remove_tag.md diff --git a/test/specs/run-spec.js b/test/specs/run-spec.js index 2702c76f68..b6d0c17e27 100644 --- a/test/specs/run-spec.js +++ b/test/specs/run-spec.js @@ -16,6 +16,8 @@ function runSpecs(title, dir, showCompletionTable, options) { spec.options = Object.assign({}, options, (spec.options || {})); const example = (spec.example ? ' example ' + spec.example : ''); const passFail = (spec.shouldFail ? 'fail' : 'pass'); + if (spec.options.sanitizerRemoveHtml) + spec.options.sanitizer = () => ''; (spec.only ? fit : it)('should ' + passFail + example, () => { const before = process.hrtime(); if (spec.shouldFail) { @@ -40,3 +42,4 @@ runSpecs('CommonMark', './commonmark', true, { headerIds: false }); runSpecs('Original', './original', false, { gfm: false }); runSpecs('New', './new'); runSpecs('ReDOS', './redos'); +runSpecs('Security', './security', false, { silent: true /* no deprecation warnings */ }); \ No newline at end of file diff --git a/test/specs/security/sanitizer_bypass.html b/test/specs/security/sanitizer_bypass.html new file mode 100644 index 0000000000..fb35223cf0 --- /dev/null +++ b/test/specs/security/sanitizer_bypass.html @@ -0,0 +1,6 @@ +

AAA<script> <img <script> src=x onerror=alert(1) />BBB

+ +

AAA<sometag> <img <sometag> src=x onerror=alert(1)BBB

+ +

<a>a2<a2t>a2</a> b <c>c</c> d

+

text

diff --git a/test/specs/security/sanitizer_bypass.md b/test/specs/security/sanitizer_bypass.md new file mode 100644 index 0000000000..99091d0198 --- /dev/null +++ b/test/specs/security/sanitizer_bypass.md @@ -0,0 +1,9 @@ +--- +sanitize: true +--- +AAA