sanitize-html 1.18.1 → 1.18.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sanitize-html",
3
- "version": "1.18.1",
3
+ "version": "1.18.5",
4
4
  "description": "Clean up user-submitted HTML, preserving whitelisted elements and whitelisted attributes on a per-element basis",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
package/src/index.js CHANGED
@@ -4,7 +4,7 @@ var quoteRegexp = require('lodash.escaperegexp');
4
4
  var cloneDeep = require('lodash.clonedeep');
5
5
  var mergeWith = require('lodash.mergewith');
6
6
  var isString = require('lodash.isstring');
7
- var isPlainObject = require('lodash.isPlainObject');
7
+ var isPlainObject = require('lodash.isplainobject');
8
8
  var srcset = require('srcset');
9
9
  var postcss = require('postcss');
10
10
  var url = require('url');
@@ -240,13 +240,10 @@ function sanitizeHtml(html, options, _recursing) {
240
240
  }
241
241
  }
242
242
  if (name === 'iframe' && a === 'src') {
243
- //Check if value contains proper hostname prefix
244
- if (value.substring(0, 2) === '//') {
245
- var prefix = 'https:';
246
- value = prefix.concat(value);
247
- }
248
243
  try {
249
- parsed = url.parse(value);
244
+ // naughtyHref is in charge of whether protocol relative URLs
245
+ // are cool. We should just accept them
246
+ parsed = url.parse(value, false, true);
250
247
  if (options.allowedIframeHostnames) {
251
248
  var whitelistedHostnames = options.allowedIframeHostnames.find(function(hostname) {
252
249
  return hostname === parsed.hostname;
@@ -414,7 +411,10 @@ function sanitizeHtml(html, options, _recursing) {
414
411
  if (typeof(s) !== 'string') {
415
412
  s = s + '';
416
413
  }
417
- return s.replace(/\&/g, '&amp;').replace(/</g, '&lt;').replace(/\>/g, '&gt;').replace(/\"/g, '&quot;');
414
+ return s.replace(/&(?![a-zA-Z0-9#]{1,7};)/g, '&amp;') // Match ampersands not part of existing HTML entity
415
+ .replace(/</g, '&lt;')
416
+ .replace(/\>/g, '&gt;')
417
+ .replace(/\"/g, '&quot;');
418
418
  }
419
419
 
420
420
  function naughtyHref(name, href) {
package/test/test.js CHANGED
@@ -647,7 +647,7 @@ describe('sanitizeHtml', function() {
647
647
  }), '<span style="color:yellow;text-align:center;font-family:helvetica;"></span>'
648
648
  );
649
649
  });
650
- it('Should allow only hostnames in an iframe that are whitelisted', function() {
650
+ it('Should allow hostnames in an iframe that are whitelisted', function() {
651
651
  assert.equal(
652
652
  sanitizeHtml('<iframe src="https://www.youtube.com/embed/c2IlcS7AHxM"></iframe>', {
653
653
          allowedTags: ['p', 'iframe', 'a', 'img', 'i'],
@@ -667,7 +667,7 @@ describe('sanitizeHtml', function() {
667
667
  });
668
668
  it('Should not allow iframe urls that do not have proper hostname', function() {
669
669
  assert.equal(
670
- sanitizeHtml('<iframe src="//www.vimeo.com/embed/c2IlcS7AHxM"></iframe>', {
670
+ sanitizeHtml('<iframe src="https://www.vimeo.com/embed/c2IlcS7AHxM"></iframe>', {
671
671
          allowedTags: ['p', 'iframe', 'a', 'img', 'i'],
672
672
          allowedAttributes: {'iframe': ['src', 'href'], 'a': ['src', 'href'], 'img': ['src']},
673
673
          allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com']
@@ -682,6 +682,32 @@ describe('sanitizeHtml', function() {
682
682
  }), '<iframe src="https://www.vimeo.com/embed/c2IlcS7AHxM"></iframe>'
683
683
  );
684
684
  });
685
+ it('Should allow relative URLs for iframes', function() {
686
+ assert.equal(
687
+ sanitizeHtml('<iframe src="/foo"></iframe>', {
688
+         allowedTags: ['p', 'iframe', 'a', 'img', 'i'],
689
+         allowedAttributes: {'iframe': ['src', 'href'], 'a': ['src', 'href'], 'img': ['src']}
690
+ }), '<iframe src="/foo"></iframe>'
691
+ );
692
+ });
693
+ it('Should allow protocol-relative URLs for the right domain for iframes', function() {
694
+ assert.equal(
695
+ sanitizeHtml('<iframe src="//www.youtube.com/embed/c2IlcS7AHxM"></iframe>', {
696
+         allowedTags: ['p', 'iframe', 'a', 'img', 'i'],
697
+         allowedAttributes: {'iframe': ['src', 'href'], 'a': ['src', 'href'], 'img': ['src']},
698
+         allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com']
699
+ }), '<iframe src="//www.youtube.com/embed/c2IlcS7AHxM"></iframe>'
700
+ );
701
+ });
702
+ it('Should not allow protocol-relative iframe urls that do not have proper hostname', function() {
703
+ assert.equal(
704
+ sanitizeHtml('<iframe src="//www.vimeo.com/embed/c2IlcS7AHxM"></iframe>', {
705
+         allowedTags: ['p', 'iframe', 'a', 'img', 'i'],
706
+         allowedAttributes: {'iframe': ['src', 'href'], 'a': ['src', 'href'], 'img': ['src']},
707
+         allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com']
708
+ }), '<iframe></iframe>'
709
+ );
710
+ });
685
711
  it('Should only allow attributes to have any combination of specific values', function() {
686
712
  assert.equal(
687
713
  sanitizeHtml('<iframe name=\"IFRAME\" allowfullscreen=\"true\" sandbox=\"allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts allow-top-navigation\"></iframe>',{
@@ -722,4 +748,17 @@ describe('sanitizeHtml', function() {
722
748
  allowedSchemes: sanitizeHtml.defaults.allowedSchemes.concat([ 'tel' ]),
723
749
  }), '<q cite=\"http://www.google.com\">HTTP</q><q cite=\"https://www.google.com\">HTTPS</q><q cite=\"mailto://www.google.com\">MAILTO</q><q cite=\"tel://www.google.com\">TEL</q><q cite=\"ftp://www.google.com\">FTP</q><q>DATA</q><q>LDAP</q><q>ACROBAT</q><q>VBSCRIPT</q><q>FILE</q><q>RLOGIN</q><q>WEBCAL</q><q>JAVASCRIPT</q><q>MMS</q>');
724
750
  });
751
+ it('Should encode &, <, > and "', function() {
752
+ assert.equal(sanitizeHtml('"< & >"'), '&quot;&lt; &amp; &gt;&quot;');
753
+ });
754
+ it('Should not double encode ampersands on HTML entities', function() {
755
+ var textIn = 'This &amp; & that &reg; &#x0000A; &#10; &plusmn; OK?';
756
+ var expectedResult = 'This &amp; &amp; that &reg; &#x0000A; &#10; &plusmn; OK?';
757
+ var sanitizeHtmlOptions = {
758
+ parser: {
759
+ decodeEntities: false
760
+ }
761
+ };
762
+ assert.equal(sanitizeHtml(textIn, sanitizeHtmlOptions), expectedResult);
763
+ });
725
764
  });