HtmlXSSUtils.js 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. 'use strict';
  2. /**
  3. * Licensed Materials - Property of IBM
  4. * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2014, 2018
  5. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  6. */
  7. define([], function () {
  8. var blackListContentTags = ['body', 'embed', 'script', 'object', 'applet', 'meta', 'style', 'link'];
  9. return {
  10. /**
  11. * Cleans the provided html string input to only the supplied array of whiteListedElements
  12. * @param {String} input Input html to process
  13. * @param {String | Array} whiteListedElements all whitelisted html tags as an array. ie ['<div>', '<p>'...] or as a string '<div><p>'
  14. * @param {Boolean} removeComments if true, strips html comments
  15. */
  16. cleanseContentElements: function cleanseContentElements(input, whiteListedElements, removeComments) {
  17. if (!input) {
  18. return null;
  19. }
  20. whiteListedElements = whiteListedElements || [];
  21. // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
  22. var allowed = ((whiteListedElements + '').toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join('');
  23. var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi;
  24. if (removeComments) {
  25. var commentsAndTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
  26. input = input.replace(commentsAndTags, '');
  27. }
  28. return input.replace(tags, function ($0, $1) {
  29. return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
  30. });
  31. },
  32. isValidHtmlContent: function isValidHtmlContent(widgetContent) {
  33. return !this.containsTag(widgetContent) && !this.containsBlackListedAttributes(widgetContent) && this.isHtmlSafe(widgetContent);
  34. },
  35. containsTag: function containsTag(widgetContent) {
  36. // Validate by matching whole tag name
  37. // ie. '<tag attr=...', '<tag>', '<tag/>', '<tag'
  38. var re = new RegExp('<(' + blackListContentTags.join('|') + ')(\\s|\\/|>|$)', 'i');
  39. return re.test(widgetContent);
  40. },
  41. containsBlackListedAttributes: function containsBlackListedAttributes(widgetContent) {
  42. // Block any attribute that starts with 'on'
  43. var re = new RegExp('<\\w+[^>]*\\bon\\w+\\s*=', 'i');
  44. return re.test(widgetContent);
  45. },
  46. isHtmlSafe: function isHtmlSafe(s) {
  47. var matches = s.match(/<\s*\w+\b[^>]+\s*>/g);
  48. if (!matches) {
  49. return true;
  50. }
  51. return [true].concat(matches). // return all Html elements with some attributes
  52. reduce( // reduce matches to true/false if valid or not
  53. function (prevValue, el) {
  54. // s is attribute, like class='a b c' or src='url()'
  55. // return true if attribute starts with javascript
  56. return prevValue && (el.match(/\w+\s*=\s*"?\s*javascript/gi) ? false : true);
  57. });
  58. },
  59. /**
  60. * check html strings is valid. If not, we reset it
  61. */
  62. sanitizeHtml: function sanitizeHtml(html) {
  63. if (!html || !this.isValidHtmlContent(html)) {
  64. return '';
  65. }
  66. return html;
  67. }
  68. };
  69. });
  70. //# sourceMappingURL=HtmlXSSUtils.js.map