fix(gateway): purify global notice HTML
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
|
||||
const safeNamedColor =
|
||||
/^(?:black|silver|gray|white|maroon|red|purple|fuchsia|green|lime|olive|yellow|navy|blue|teal|aqua|orange|cyan|magenta|skyblue|orangered|limegreen|darkorange)$/i;
|
||||
const safeFontColor = (value: string): boolean => /^#[0-9a-f]{3,8}$/i.test(value) || safeNamedColor.test(value);
|
||||
const safeFontFace = /^[\p{L}\p{N}\s,'".-]+$/u;
|
||||
|
||||
const options: sanitizeHtml.IOptions = {
|
||||
allowedTags: ['br', 'b', 'strong', 'em', 'i', 'u', 's', 'strike', 'small', 'sup', 'sub', 'span', 'a', 'font'],
|
||||
allowedAttributes: {
|
||||
'*': ['style', 'title'],
|
||||
a: ['href', 'target', 'rel', 'title', 'style'],
|
||||
font: ['color', 'size', 'face', 'style', 'title'],
|
||||
},
|
||||
allowedSchemes: ['http', 'https', 'mailto', 'tel'],
|
||||
allowProtocolRelative: false,
|
||||
allowedStyles: {
|
||||
'*': {
|
||||
color: [/^#[0-9a-f]{3,8}$/i, /^rgba?\([\d\s.,%]+\)$/i, safeNamedColor],
|
||||
'font-size': [
|
||||
/^\d+(?:\.\d+)?(?:px|pt|em|rem|%)$/i,
|
||||
/^(?:xx-small|x-small|small|medium|large|x-large|xx-large)$/i,
|
||||
],
|
||||
'font-style': [/^(?:normal|italic|oblique)$/i],
|
||||
'font-weight': [/^(?:normal|bold|bolder|lighter|[1-9]00)$/i],
|
||||
'text-decoration': [
|
||||
/^(?:none|underline|line-through|overline)(?:\s+(?:underline|line-through|overline))*$/i,
|
||||
],
|
||||
},
|
||||
},
|
||||
transformTags: {
|
||||
a: (tagName, attribs) => {
|
||||
const target = attribs.target === '_blank' || attribs.target === '_self' ? attribs.target : undefined;
|
||||
const { target: _target, rel: _rel, ...rest } = attribs;
|
||||
return {
|
||||
tagName,
|
||||
attribs: target
|
||||
? {
|
||||
...rest,
|
||||
target,
|
||||
...(target === '_blank' ? { rel: 'noopener noreferrer nofollow' } : {}),
|
||||
}
|
||||
: rest,
|
||||
};
|
||||
},
|
||||
font: (tagName, attribs) => ({
|
||||
tagName,
|
||||
attribs: {
|
||||
...(attribs.color && safeFontColor(attribs.color) ? { color: attribs.color } : {}),
|
||||
...(attribs.size && /^[1-7]$/.test(attribs.size) ? { size: attribs.size } : {}),
|
||||
...(attribs.face && safeFontFace.test(attribs.face) ? { face: attribs.face } : {}),
|
||||
...(attribs.style ? { style: attribs.style } : {}),
|
||||
...(attribs.title ? { title: attribs.title } : {}),
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Canonicalizes Ref-compatible gateway notice markup on both writes and reads.
|
||||
* Reads are purified again so pre-existing rows cannot execute active content.
|
||||
*/
|
||||
export const purifyGatewayNoticeHtml = (value: string | null | undefined): string => {
|
||||
if (!value) return '';
|
||||
return sanitizeHtml(value, options);
|
||||
};
|
||||
Reference in New Issue
Block a user