Socket
Socket
Sign inDemoInstall

sanitize-html

Package Overview
Dependencies
Maintainers
9
Versions
113
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sanitize-html - npm Package Compare versions

Comparing version 1.19.2 to 1.19.3

2

CHANGELOG.md
## Changelog
1.19.3: reverted to `postcss` due to a [reported issue with `css-tree` that might or might not have XSS implications](https://github.com/punkave/sanitize-html/issues/269).
1.19.2:

@@ -4,0 +6,0 @@

97

dist/index.js

@@ -11,3 +11,3 @@ 'use strict';

var srcset = require('srcset');
var csstree = require('css-tree');
var postcss = require('postcss');
var url = require('url');

@@ -342,21 +342,7 @@

try {
var ast = csstree.parse(name + " {" + value + "}");
var selectors = rulesForSelector(name, options.allowedStyles || {});
var abstractSyntaxTree = postcss.parse(name + " {" + value + "}");
var filteredAST = filterCss(abstractSyntaxTree, options.allowedStyles);
csstree.walk(ast, function (node, item, list) {
if (node.type === 'Declaration' && list) {
var value = csstree.generate(node.value);
var rules = selectors[node.property];
value = stringifyStyleAttributes(filteredAST);
if (rules !== undefined && rules.every(function (rule) {
return !value.match(rule);
})) {
list.remove(item);
}
}
});
value = csstree.generate(ast).slice(name.length + 1);
value = value.slice(0, value.length - 1);
if (value.length === 0) {

@@ -366,5 +352,2 @@ delete frame.attribs[a];

}
// preserve the final semicolon
value += ';';
} catch (e) {

@@ -526,6 +509,22 @@ delete frame.attribs[a];

function rulesForSelector(selector, allowedStyles) {
/**
* Filters user input css properties by whitelisted regex attributes.
*
* @param {object} abstractSyntaxTree - Object representation of CSS attributes.
* @property {array[Declaration]} abstractSyntaxTree.nodes[0] - Each object cointains prop and value key, i.e { prop: 'color', value: 'red' }.
* @param {object} allowedStyles - Keys are properties (i.e color), value is list of permitted regex rules (i.e /green/i).
* @return {object} - Abstract Syntax Tree with filtered style attributes.
*/
function filterCss(abstractSyntaxTree, allowedStyles) {
if (!allowedStyles) {
return abstractSyntaxTree;
}
var filteredAST = cloneDeep(abstractSyntaxTree);
var astRules = abstractSyntaxTree.nodes[0];
var selectedRule;
// Merge global and tag-specific styles into new AST.
if (allowedStyles[selector] && allowedStyles['*']) {
return mergeWith(cloneDeep(allowedStyles[selector]), allowedStyles['*'], function (objValue, srcValue) {
if (allowedStyles[astRules.selector] && allowedStyles['*']) {
selectedRule = mergeWith(cloneDeep(allowedStyles[astRules.selector]), allowedStyles['*'], function (objValue, srcValue) {
if (Array.isArray(objValue)) {

@@ -535,7 +534,55 @@ return objValue.concat(srcValue);

});
} else {
selectedRule = allowedStyles[astRules.selector] || allowedStyles['*'];
}
return allowedStyles[selector] || allowedStyles['*'] || {};
if (selectedRule) {
filteredAST.nodes[0].nodes = astRules.nodes.reduce(filterDeclarations(selectedRule), []);
}
return filteredAST;
}
/**
* Extracts the style attribues from an AbstractSyntaxTree and formats those
* values in the inline style attribute format.
*
* @param {AbstractSyntaxTree} filteredAST
* @return {string} - Example: "color:yellow;text-align:center;font-family:helvetica;"
*/
function stringifyStyleAttributes(filteredAST) {
return filteredAST.nodes[0].nodes.reduce(function (extractedAttributes, attributeObject) {
extractedAttributes.push(attributeObject.prop + ':' + attributeObject.value + ';');
return extractedAttributes;
}, []).join('');
}
/**
* Filters the existing attributes for the given property. Discards any attributes
* which don't match the whitelist.
*
* @param {object} selectedRule - Example: { color: red, font-family: helvetica }
* @param {array} allowedDeclarationsList - List of declarations which pass whitelisting.
* @param {object} attributeObject - Object representing the current css property.
* @property {string} attributeObject.type - Typically 'declaration'.
* @property {string} attributeObject.prop - The CSS property, i.e 'color'.
* @property {string} attributeObject.value - The corresponding value to the css property, i.e 'red'.
* @return {function} - When used in Array.reduce, will return an array of Declaration objects
*/
function filterDeclarations(selectedRule) {
return function (allowedDeclarationsList, attributeObject) {
// If this property is whitelisted...
if (selectedRule.hasOwnProperty(attributeObject.prop)) {
var matchesRegex = selectedRule[attributeObject.prop].some(function (regularExpression) {
return regularExpression.test(attributeObject.value);
});
if (matchesRegex) {
allowedDeclarationsList.push(attributeObject);
}
}
return allowedDeclarationsList;
};
}
function filterClasses(classes, allowed) {

@@ -542,0 +589,0 @@ if (!allowed) {

{
"name": "sanitize-html",
"version": "1.19.2",
"version": "1.19.3",
"description": "Clean up user-submitted HTML, preserving whitelisted elements and whitelisted attributes on a per-element basis",

@@ -29,3 +29,2 @@ "main": "dist/index.js",

"chalk": "^2.4.1",
"css-tree": "^1.0.0-alpha.29",
"htmlparser2": "^3.10.0",

@@ -37,2 +36,3 @@ "lodash.clonedeep": "^4.5.0",

"lodash.mergewith": "^4.6.1",
"postcss": "^7.0.5",
"srcset": "^1.0.0",

@@ -39,0 +39,0 @@ "xtend": "^4.0.1"

@@ -9,3 +9,3 @@ var htmlparser = require('htmlparser2');

var srcset = require('srcset');
var csstree = require('css-tree');
var postcss = require('postcss');
var url = require('url');

@@ -303,19 +303,7 @@

try {
var ast = csstree.parse(name + " {" + value + "}");
var selectors = rulesForSelector(name, options.allowedStyles || {});
var abstractSyntaxTree = postcss.parse(name + " {" + value + "}");
var filteredAST = filterCss(abstractSyntaxTree, options.allowedStyles);
csstree.walk(ast, function(node, item, list) {
if (node.type === 'Declaration' && list) {
var value = csstree.generate(node.value);
var rules = selectors[node.property];
value = stringifyStyleAttributes(filteredAST);
if (rules !== undefined && rules.every(function (rule) { return !value.match(rule); })) {
list.remove(item)
}
}
})
value = csstree.generate(ast).slice(name.length + 1);
value = value.slice(0, value.length - 1);
if(value.length === 0) {

@@ -325,6 +313,2 @@ delete frame.attribs[a];

}
// preserve the final semicolon
value += ';';
} catch (e) {

@@ -487,7 +471,23 @@ delete frame.attribs[a];

function rulesForSelector(selector, allowedStyles) {
/**
* Filters user input css properties by whitelisted regex attributes.
*
* @param {object} abstractSyntaxTree - Object representation of CSS attributes.
* @property {array[Declaration]} abstractSyntaxTree.nodes[0] - Each object cointains prop and value key, i.e { prop: 'color', value: 'red' }.
* @param {object} allowedStyles - Keys are properties (i.e color), value is list of permitted regex rules (i.e /green/i).
* @return {object} - Abstract Syntax Tree with filtered style attributes.
*/
function filterCss(abstractSyntaxTree, allowedStyles) {
if (!allowedStyles) {
return abstractSyntaxTree;
}
var filteredAST = cloneDeep(abstractSyntaxTree);
var astRules = abstractSyntaxTree.nodes[0];
var selectedRule;
// Merge global and tag-specific styles into new AST.
if (allowedStyles[selector] && allowedStyles['*']) {
return mergeWith(
cloneDeep(allowedStyles[selector]),
if (allowedStyles[astRules.selector] && allowedStyles['*']) {
selectedRule = mergeWith(
cloneDeep(allowedStyles[astRules.selector]),
allowedStyles['*'],

@@ -500,7 +500,59 @@ function(objValue, srcValue) {

);
} else {
selectedRule = allowedStyles[astRules.selector] || allowedStyles['*'];
}
return allowedStyles[selector] || allowedStyles['*'] || {};
if (selectedRule) {
filteredAST.nodes[0].nodes = astRules.nodes.reduce(filterDeclarations(selectedRule), []);
}
return filteredAST;
}
/**
* Extracts the style attribues from an AbstractSyntaxTree and formats those
* values in the inline style attribute format.
*
* @param {AbstractSyntaxTree} filteredAST
* @return {string} - Example: "color:yellow;text-align:center;font-family:helvetica;"
*/
function stringifyStyleAttributes(filteredAST) {
return filteredAST.nodes[0].nodes
.reduce(function(extractedAttributes, attributeObject) {
extractedAttributes.push(
attributeObject.prop + ':' + attributeObject.value + ';'
);
return extractedAttributes;
}, [])
.join('');
}
/**
* Filters the existing attributes for the given property. Discards any attributes
* which don't match the whitelist.
*
* @param {object} selectedRule - Example: { color: red, font-family: helvetica }
* @param {array} allowedDeclarationsList - List of declarations which pass whitelisting.
* @param {object} attributeObject - Object representing the current css property.
* @property {string} attributeObject.type - Typically 'declaration'.
* @property {string} attributeObject.prop - The CSS property, i.e 'color'.
* @property {string} attributeObject.value - The corresponding value to the css property, i.e 'red'.
* @return {function} - When used in Array.reduce, will return an array of Declaration objects
*/
function filterDeclarations(selectedRule) {
return function (allowedDeclarationsList, attributeObject) {
// If this property is whitelisted...
if (selectedRule.hasOwnProperty(attributeObject.prop)) {
var matchesRegex = selectedRule[attributeObject.prop].some(function(regularExpression) {
return regularExpression.test(attributeObject.value);
});
if (matchesRegex) {
allowedDeclarationsList.push(attributeObject);
}
}
return allowedDeclarationsList;
};
}
function filterClasses(classes, allowed) {

@@ -507,0 +559,0 @@ if (!allowed) {

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc