@exadel/esl
Version:
Exadel Smart Library (ESL) is the lightweight custom elements library that provide a set of super-flexible components
55 lines (54 loc) • 2.01 kB
JavaScript
/** checks if the attribute is dangerous */
const isDangerousAttribute = (name, value) => {
const val = value.replace(/\s+/g, '').toLowerCase();
if (['src', 'data', 'href', 'xlink:href'].includes(name)
&& (val.includes('javascript:') || val.includes('data:text/html')))
return true;
return name.indexOf('on') === 0;
};
/** loops through each attribute, if it's dangerous, remove it */
const removeDangerousAttributes = (el) => {
Array.from(el.attributes).forEach(({ name, value }) => {
if (isDangerousAttribute(name, value)) {
el.removeAttribute(name);
}
});
};
/** removes malicious attributes from element and its children */
const sanitizeElAttributes = (body) => {
Array.from(body.children).forEach((el) => {
removeDangerousAttributes(el);
sanitizeElAttributes(el);
});
};
/** removes script elements inside element */
const removeScripts = (body) => {
const scripts = body.querySelectorAll('script');
Array.from(scripts).forEach((script) => script.remove());
};
const filterElements = (body, allowedTopLevelTags) => {
if (!allowedTopLevelTags.length)
return;
Array.from(body.childNodes).forEach((el) => {
if (!allowedTopLevelTags.includes(el.tagName))
body.removeChild(el);
});
};
/**
* Sanitizes html string from malicious attributes, values, and scripts
* Can also filter elements at the top nesting level by tag names.
* @param html - html string to sanitize
* @param allowedTopLevelTags - array of allowed tag names
*/
export function sanitize(html, allowedTopLevelTags = []) {
// converts the string to an HTML document
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const body = doc.body || document.createElement('body');
// sanitizes html
removeScripts(body);
sanitizeElAttributes(body);
// filter allowed tags
filterElements(body, allowedTopLevelTags);
return body.innerHTML;
}