sanitize-html
Advanced tools
+83
-39
@@ -91,3 +91,4 @@ const htmlparser = require('htmlparser2'); | ||
| let result = ''; | ||
| // Used for hot swapping the result variable with an empty string in order to "capture" the text written to it. | ||
| // Used for hot swapping the result variable with an empty string | ||
| // in order to "capture" the text written to it. | ||
| let tempResult = ''; | ||
@@ -123,3 +124,4 @@ | ||
| const tagAllowed = function (name) { | ||
| return options.allowedTags === false || (options.allowedTags || []).indexOf(name) > -1; | ||
| return options.allowedTags === false || | ||
| (options.allowedTags || []).indexOf(name) > -1; | ||
| }; | ||
@@ -306,3 +308,4 @@ | ||
| const isBeingEscaped = skip && (options.disallowedTagsMode === 'escape' || options.disallowedTagsMode === 'recursiveEscape'); | ||
| const shouldPreserveEscapedAttributes = isBeingEscaped && options.preserveEscapedAttributes; | ||
| const shouldPreserveEscapedAttributes = isBeingEscaped && | ||
| options.preserveEscapedAttributes; | ||
@@ -321,4 +324,6 @@ if (shouldPreserveEscapedAttributes) { | ||
| } | ||
| // If the value is empty, check if the attribute is in the allowedEmptyAttributes array. | ||
| // If it is not in the allowedEmptyAttributes array, and it is a known non-boolean attribute, delete it | ||
| // If the value is empty, check if the attribute is | ||
| // in the allowedEmptyAttributes array. | ||
| // If it is not in the allowedEmptyAttributes array, | ||
| // and it is a known non-boolean attribute, delete it | ||
| // List taken from https://html.spec.whatwg.org/multipage/indices.html#attributes-3 | ||
@@ -334,5 +339,7 @@ if (value === '' && (!options.allowedEmptyAttributes.includes(a)) && | ||
| if (!allowedAttributesMap || | ||
| (has(allowedAttributesMap, name) && allowedAttributesMap[name].indexOf(a) !== -1) || | ||
| (has(allowedAttributesMap, name) && | ||
| allowedAttributesMap[name].indexOf(a) !== -1) || | ||
| (allowedAttributesMap['*'] && allowedAttributesMap['*'].indexOf(a) !== -1) || | ||
| (has(allowedAttributesGlobMap, name) && allowedAttributesGlobMap[name].test(a)) || | ||
| (has(allowedAttributesGlobMap, name) && | ||
| allowedAttributesGlobMap[name].test(a)) || | ||
| (allowedAttributesGlobMap['*'] && allowedAttributesGlobMap['*'].test(a))) { | ||
@@ -381,8 +388,10 @@ passedAllowedAttributesMapCheck = true; | ||
| if (options.allowedScriptHostnames || options.allowedScriptDomains) { | ||
| const allowedHostname = (options.allowedScriptHostnames || []).find(function (hostname) { | ||
| return hostname === parsed.url.hostname; | ||
| }); | ||
| const allowedDomain = (options.allowedScriptDomains || []).find(function(domain) { | ||
| return parsed.url.hostname === domain || parsed.url.hostname.endsWith(`.${domain}`); | ||
| }); | ||
| const allowedHostname = (options.allowedScriptHostnames || []) | ||
| .find(function (hostname) { | ||
| return hostname === parsed.url.hostname; | ||
| }); | ||
| const allowedDomain = (options.allowedScriptDomains || []) | ||
| .find(function(domain) { | ||
| return parsed.url.hostname === domain || parsed.url.hostname.endsWith(`.${domain}`); | ||
| }); | ||
| allowed = allowedHostname || allowedDomain; | ||
@@ -411,9 +420,14 @@ } | ||
| : (!options.allowedIframeHostnames && !options.allowedIframeDomains); | ||
| } else if (options.allowedIframeHostnames || options.allowedIframeDomains) { | ||
| const allowedHostname = (options.allowedIframeHostnames || []).find(function (hostname) { | ||
| return hostname === parsed.url.hostname; | ||
| }); | ||
| const allowedDomain = (options.allowedIframeDomains || []).find(function(domain) { | ||
| return parsed.url.hostname === domain || parsed.url.hostname.endsWith(`.${domain}`); | ||
| }); | ||
| } else if ( | ||
| options.allowedIframeHostnames || | ||
| options.allowedIframeDomains | ||
| ) { | ||
| const allowedHostname = (options.allowedIframeHostnames || []) | ||
| .find(function (hostname) { | ||
| return hostname === parsed.url.hostname; | ||
| }); | ||
| const allowedDomain = (options.allowedIframeDomains || []) | ||
| .find(function(domain) { | ||
| return parsed.url.hostname === domain || parsed.url.hostname.endsWith(`.${domain}`); | ||
| }); | ||
| allowed = allowedHostname || allowedDomain; | ||
@@ -472,5 +486,13 @@ } | ||
| if (allowedSpecificClasses && allowedWildcardClasses) { | ||
| value = filterClasses(value, deepmerge(allowedSpecificClasses, allowedWildcardClasses), allowedClassesGlobs); | ||
| value = filterClasses( | ||
| value, | ||
| deepmerge(allowedSpecificClasses, allowedWildcardClasses), | ||
| allowedClassesGlobs | ||
| ); | ||
| } else { | ||
| value = filterClasses(value, allowedSpecificClasses || allowedWildcardClasses, allowedClassesGlobs); | ||
| value = filterClasses( | ||
| value, | ||
| allowedSpecificClasses || allowedWildcardClasses, | ||
| allowedClassesGlobs | ||
| ); | ||
| } | ||
@@ -486,3 +508,6 @@ if (!value.length) { | ||
| const abstractSyntaxTree = postcssParse(name + ' {' + value + '}', { map: false }); | ||
| const filteredAST = filterCss(abstractSyntaxTree, options.allowedStyles); | ||
| const filteredAST = filterCss( | ||
| abstractSyntaxTree, | ||
| options.allowedStyles | ||
| ); | ||
@@ -620,3 +645,4 @@ value = stringifyStyleAttributes(filteredAST); | ||
| // remove the opening tag from the result | ||
| result = result.substring(0, frame.tagPosition) + result.substring(frame.tagPosition + frame.openingTagLength); | ||
| result = result.substring(0, frame.tagPosition) + | ||
| result.substring(frame.tagPosition + frame.openingTagLength); | ||
| return; | ||
@@ -656,2 +682,12 @@ } else if (filterResult) { | ||
| if (options.disallowedTagsMode === 'escape' || options.disallowedTagsMode === 'recursiveEscape') { | ||
| const lastParsedIndex = parser.endIndex; | ||
| if (lastParsedIndex != null && lastParsedIndex >= 0 && lastParsedIndex < html.length) { | ||
| const unparsed = html.substring(lastParsedIndex); | ||
| result += escapeHtml(unparsed); | ||
| } else if ((lastParsedIndex == null || lastParsedIndex < 0) && html.length > 0 && result === '') { | ||
| result = escapeHtml(html); | ||
| } | ||
| } | ||
| return result; | ||
@@ -767,4 +803,6 @@ | ||
| * @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). | ||
| * @property {array[Declaration]} abstractSyntaxTree.nodes[0] - | ||
| * Each object contains 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} - The modified tree. | ||
@@ -791,3 +829,4 @@ */ | ||
| if (selectedRule) { | ||
| abstractSyntaxTree.nodes[0].nodes = astRules.nodes.reduce(filterDeclarations(selectedRule), []); | ||
| abstractSyntaxTree.nodes[0].nodes = astRules.nodes | ||
| .reduce(filterDeclarations(selectedRule), []); | ||
| } | ||
@@ -803,3 +842,4 @@ | ||
| * @param {AbstractSyntaxTree} filteredAST | ||
| * @return {string} - Example: "color:yellow;text-align:center !important;font-family:helvetica;" | ||
| * @return {string} - Example: | ||
| * "color:yellow;text-align:center !important;font-family:helvetica;" | ||
| */ | ||
@@ -821,9 +861,12 @@ function stringifyStyleAttributes(filteredAST) { | ||
| * | ||
| * @param {object} selectedRule - Example: { color: red, font-family: helvetica } | ||
| * @param {array} allowedDeclarationsList - List of declarations which pass the allowlist. | ||
| * @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 | ||
| * @param {object} selectedRule - Example: { color: red, font-family: helvetica } | ||
| * @param {array} allowedDeclarationsList - List of declarations | ||
| * which pass the allowlist. | ||
| * @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 | ||
| */ | ||
@@ -834,5 +877,6 @@ function filterDeclarations(selectedRule) { | ||
| if (has(selectedRule, attributeObject.prop)) { | ||
| const matchesRegex = selectedRule[attributeObject.prop].some(function(regularExpression) { | ||
| return regularExpression.test(attributeObject.value); | ||
| }); | ||
| const matchesRegex = selectedRule[attributeObject.prop] | ||
| .some(function(regularExpression) { | ||
| return regularExpression.test(attributeObject.value); | ||
| }); | ||
@@ -969,5 +1013,5 @@ if (matchesRegex) { | ||
| tagName: newTagName, | ||
| attribs: attribs | ||
| attribs | ||
| }; | ||
| }; | ||
| }; |
+14
-13
| { | ||
| "name": "sanitize-html", | ||
| "version": "2.17.0", | ||
| "version": "2.17.1", | ||
| "description": "Clean up user-submitted HTML, preserving allowlisted elements and allowlisted attributes on a per-element basis", | ||
@@ -10,9 +10,8 @@ "sideEffects": false, | ||
| ], | ||
| "scripts": { | ||
| "test": "npx eslint . && mocha test/test.js" | ||
| }, | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/apostrophecms/sanitize-html.git" | ||
| "url": "https://github.com/apostrophecms/apostrophe.git", | ||
| "directory": "packages/sanitize-html" | ||
| }, | ||
| "homepage": "https://github.com/apostrophecms/apostrophe/tree/main/packages/sanitize-html#readme", | ||
| "keywords": [ | ||
@@ -35,12 +34,14 @@ "html", | ||
| "devDependencies": { | ||
| "eslint": "^7.3.1", | ||
| "eslint-config-apostrophe": "^3.4.0", | ||
| "eslint-config-standard": "^14.1.1", | ||
| "eslint-plugin-import": "^2.25.2", | ||
| "eslint-plugin-node": "^11.1.0", | ||
| "eslint-plugin-promise": "^4.2.1", | ||
| "eslint-plugin-standard": "^4.0.1", | ||
| "eslint": "^9.39.1", | ||
| "mocha": "^10.2.0", | ||
| "sinon": "^9.0.2" | ||
| "sinon": "^9.0.2", | ||
| "eslint-config-apostrophe": "^6.0.2" | ||
| }, | ||
| "apostropheTestConfig": { | ||
| "requiresMongo": false | ||
| }, | ||
| "scripts": { | ||
| "test": "npm run lint && mocha", | ||
| "lint": "eslint ." | ||
| } | ||
| } |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
69754
1.36%4
-55.56%922
4.89%0
-100%