From fde54310964a20373e5db991c7dcfd90951b048e Mon Sep 17 00:00:00 2001 From: Aleksandr Dukhovnyy + + <
img src="1" onerror="alert(1)"> + + + Bold + Bold + Bold +123
+ +`; + +const safeString = sanitizer.sanitize(dangerString); + +console.log(safeString); + +/* + <img src="1" onerror="alert(1)"> + + + Bold + Bold + Bold +123
+ +*/ +``` + +## Browser support + +Although browser support is already over 95%, the specification for DOMParser is not yet fully established. [More details](https://caniuse.com/mdn-api_domparser_parsefromstring_html). diff --git a/index.js b/index.js new file mode 100644 index 0000000..3da8c06 --- /dev/null +++ b/index.js @@ -0,0 +1,51 @@ +class Sanitizer { + constructor(allowedTags = []) { + this.allowedTags = allowedTags.reduce((acc, curr) => { + const name = curr.name; + delete curr.name; + + acc[name] = curr; + + return acc; + }, {}); + this.whiteList = Object.keys(this.allowedTags); + + this.sanitize.bind(this); + } + sanitize(str) { + const wrapper = new DOMParser() + .parseFromString(str, 'text/html') + .querySelector('body'); + + const allItems = wrapper.querySelectorAll('*'); + + allItems.forEach((tag) => { + const name = tag.tagName.toLowerCase(); + + if (this.whiteList.includes(name)) { + const tagConfig = this.allowedTags[name]; + + if (tagConfig.attributes !== undefined) { + for (let i = 0; i < tag.attributes.length; i++) { + const attr = tag.attributes[i]; + + if (!tagConfig.attributes.includes(attr.name)) { + tag.removeAttribute(attr.name); + } + } + } else { + for (let i = 0; i < tag.attributes.length; i++) { + tag.removeAttribute(tag.attributes[i].name); + } + } + } else { + tag.insertAdjacentHTML('afterend', this.sanitize(tag.innerHTML)); + tag.remove(); + } + }); + + return wrapper.innerHTML; + } +} + +module.exports = Sanitizer; diff --git a/package.json b/package.json new file mode 100644 index 0000000..dbea121 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "purify-html", + "version": "1.0.1", + "description": "A minimalistic library for sanitizing strings so that they can be safely used as HTML.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Aleksandr-JS-Developer/purify-html.git" + }, + "keywords": [ + "html-sanitize", + "sanitize" + ], + "author": "alex-js-dev", + "license": "MIT", + "files": [ + "index.js" + ], + "bugs": { + "url": "https://github.com/Aleksandr-JS-Developer/purify-html/issues" + }, + "homepage": "https://github.com/Aleksandr-JS-Developer/purify-html#readme" +}