CVE-2015-3295: Improper Access Control (CWE-284)
value: markdown-it before 4.1.0 does not block data: URLs.
CWE description: The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor.
CVSS v3 base score: 5.3
Published: 2017-06-07T21:29Z
Repository: https://github.com/markdown-it/markdown-it
Language: JavaScript
Files changed: lib/index.js, test/fixtures/markdown-it/xss.txt
Commit date: 2015-03-31 00:04:52 +0300
Commit message: Disabled data URIs (allow only some whitelisted images)

Diff: diff --git a/lib/index.js b/lib/index.js
index abc1525..320b983 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -18,24 +18,45 @@ var config = {
   'default': require('./presets/default'),
   zero: require('./presets/zero'),
   commonmark: require('./presets/commonmark')
 };
 
-
-var BAD_PROTOCOLS    = [ 'vbscript', 'javascript', 'file' ];
+////////////////////////////////////////////////////////////////////////////////
+//
+// This validator does not pretent to functionality of full weight sanitizers.
+// It's a tradeoff between default security, simplicity and usability.
+// If you need different setup - override validator method as you wish. Or
+// replace it with dummy function and use external sanitizer.
+//
+
+var BAD_PROTOCOLS      = [ 'vbscript', 'javascript', 'file', 'data' ];
+var ALLOWED_DATA_MIMES = [
+  'data:image/gif',
+  'data:image/png',
+  'data:image/jpeg',
+  'data:image/webp'
+];
 
 function validateLink(url) {
   // url should be normalized at this point, and existing entities are decoded
-  //
-  var str = url.trim().toLowerCase();
 
-  if (str.indexOf(':') >= 0 && BAD_PROTOCOLS.indexOf(str.split(':')[0]) >= 0) {
+  var str      = url.trim().toLowerCase(),
+      protocol = str.split(':')[0];
+
+  if (str.indexOf(':') >= 0 && BAD_PROTOCOLS.indexOf(protocol) >= 0) {
+    if (protocol === 'data' && ALLOWED_DATA_MIMES.indexOf(str.split(';')[0]) >= 0) {
+      return true;
+    }
     return false;
   }
+
   return true;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
+
 var RECODE_HOSTNAME_FOR = [ 'http:', 'https:', 'mailto:' ];
 
 function normalizeLink(url) {
   var parsed = mdurl.parse(url, true);
 
diff --git a/test/fixtures/markdown-it/xss.txt b/test/fixtures/markdown-it/xss.txt
index 25eb361..99bfa42 100644
--- a/test/fixtures/markdown-it/xss.txt
+++ b/test/fixtures/markdown-it/xss.txt
@@ -51,10 +51,25 @@ Should not allow some protocols in links and images
 .
 <p>[xss link](javascript:alert(1))</p>
 .
 
 
+Should not allow data-uri except some whitelisted mimes
+.
+![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
+.
+<p><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt=""></p>
+.
+
+.
+[xss link](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)
+.
+<p>[xss link](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)</p>
+.
+
+
+
 Image parser use the same code base.
 .
 ![xss link](javascript:alert(1))
 .
 <p>![xss link](javascript:alert(1))</p>

Vulnerable code: 
var BAD_PROTOCOLS    = [ 'vbscript', 'javascript', 'file' ];
  //
  var str = url.trim().toLowerCase();
  if (str.indexOf(':') >= 0 && BAD_PROTOCOLS.indexOf(str.split(':')[0]) >= 0) {
Fixed code: ////////////////////////////////////////////////////////////////////////////////
//
// This validator does not pretent to functionality of full weight sanitizers.
// It's a tradeoff between default security, simplicity and usability.
// If you need different setup - override validator method as you wish. Or
// replace it with dummy function and use external sanitizer.
//

var BAD_PROTOCOLS      = [ 'vbscript', 'javascript', 'file', 'data' ];
var ALLOWED_DATA_MIMES = [
  'data:image/gif',
  'data:image/png',
  'data:image/jpeg',
  'data:image/webp'
];
  var str      = url.trim().toLowerCase(),
      protocol = str.split(':')[0];

  if (str.indexOf(':') >= 0 && BAD_PROTOCOLS.indexOf(protocol) >= 0) {
    if (protocol === 'data' && ALLOWED_DATA_MIMES.indexOf(str.split(';')[0]) >= 0) {
      return true;
    }

////////////////////////////////////////////////////////////////////////////////


Should not allow data-uri except some whitelisted mimes
.
![](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
.
<p><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt=""></p>
.

.
[xss link](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)
.
<p>[xss link](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)</p>
.