@ape.swap/bonds-sdk 7.0.4 → 7.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,23 +1,53 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
|
|
3
|
+
const TAG_WHITELIST = ['a', 'br', 'span']; // Allowed tags
|
|
4
|
+
const ATTR_WHITELIST = ['target', 'rel', 'style', 'href']; // Allowed attributes
|
|
5
|
+
const URL_PROTOCOL_WHITELIST = ['http:', 'https:', 'mailto:']; // Allowed href schemes
|
|
6
|
+
const STYLE_PROPERTY_WHITELIST = ['color']; // Allowed inline style properties
|
|
7
|
+
// Returns true only for URLs with an allowed scheme. The URL parser strips the whitespace and control
|
|
8
|
+
// characters browsers ignore, so obfuscated values like "java\tscript:" are caught too
|
|
9
|
+
function isSafeURL(value) {
|
|
10
|
+
try {
|
|
11
|
+
return URL_PROTOCOL_WHITELIST.includes(new URL(value, window.location.href).protocol);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
// Keeps only whitelisted style properties, so content can't overlay or restyle the host page
|
|
18
|
+
function sanitizeStyle(el) {
|
|
19
|
+
const { style } = el;
|
|
20
|
+
for (const property of Array.from(style)) {
|
|
21
|
+
if (!STYLE_PROPERTY_WHITELIST.includes(property))
|
|
22
|
+
style.removeProperty(property);
|
|
23
|
+
}
|
|
24
|
+
if (!style.length)
|
|
25
|
+
el.removeAttribute('style');
|
|
26
|
+
}
|
|
3
27
|
// Custom HTML sanitizer
|
|
4
28
|
function sanitizeHTML(html) {
|
|
5
|
-
|
|
6
|
-
|
|
29
|
+
if (typeof window === 'undefined' || typeof DOMParser === 'undefined')
|
|
30
|
+
return '';
|
|
7
31
|
const doc = new DOMParser().parseFromString(html, 'text/html');
|
|
8
32
|
const elements = doc.body.querySelectorAll('*');
|
|
9
33
|
for (const el of elements) {
|
|
10
34
|
// Remove elements that are not in the whitelist
|
|
11
|
-
if (!
|
|
35
|
+
if (!TAG_WHITELIST.includes(el.tagName.toLowerCase())) {
|
|
12
36
|
el?.parentNode?.removeChild(el);
|
|
13
37
|
continue;
|
|
14
38
|
}
|
|
15
39
|
// Loop through the element's attributes and remove those that are not in the whitelist
|
|
16
40
|
Array.from(el.attributes).forEach((attr) => {
|
|
17
|
-
|
|
41
|
+
const name = attr.name.toLowerCase();
|
|
42
|
+
if (!ATTR_WHITELIST.includes(name) || (name === 'href' && !isSafeURL(attr.value))) {
|
|
18
43
|
el.removeAttribute(attr.name);
|
|
19
44
|
}
|
|
20
45
|
});
|
|
46
|
+
if (el.hasAttribute('style'))
|
|
47
|
+
sanitizeStyle(el);
|
|
48
|
+
// Links opening a new tab must not get a handle on the host page (reverse tabnabbing)
|
|
49
|
+
if (el.hasAttribute('target'))
|
|
50
|
+
el.setAttribute('rel', 'noopener noreferrer');
|
|
21
51
|
}
|
|
22
52
|
return doc.body.innerHTML;
|
|
23
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/SafeHTMLComponent/index.tsx"],"sourcesContent":["import * as React from 'react'\n\
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/SafeHTMLComponent/index.tsx"],"sourcesContent":["import * as React from 'react'\n\nconst TAG_WHITELIST = ['a', 'br', 'span'] // Allowed tags\nconst ATTR_WHITELIST = ['target', 'rel', 'style', 'href'] // Allowed attributes\nconst URL_PROTOCOL_WHITELIST = ['http:', 'https:', 'mailto:'] // Allowed href schemes\nconst STYLE_PROPERTY_WHITELIST = ['color'] // Allowed inline style properties\n\n// Returns true only for URLs with an allowed scheme. The URL parser strips the whitespace and control\n// characters browsers ignore, so obfuscated values like \"java\\tscript:\" are caught too\nfunction isSafeURL(value: string) {\n try {\n return URL_PROTOCOL_WHITELIST.includes(new URL(value, window.location.href).protocol)\n } catch {\n return false\n }\n}\n\n// Keeps only whitelisted style properties, so content can't overlay or restyle the host page\nfunction sanitizeStyle(el: HTMLElement) {\n const { style } = el\n for (const property of Array.from(style)) {\n if (!STYLE_PROPERTY_WHITELIST.includes(property)) style.removeProperty(property)\n }\n if (!style.length) el.removeAttribute('style')\n}\n\n// Custom HTML sanitizer\nfunction sanitizeHTML(html: string) {\n if (typeof window === 'undefined' || typeof DOMParser === 'undefined') return ''\n\n const doc = new DOMParser().parseFromString(html, 'text/html')\n const elements = doc.body.querySelectorAll('*')\n\n for (const el of elements) {\n // Remove elements that are not in the whitelist\n if (!TAG_WHITELIST.includes(el.tagName.toLowerCase())) {\n el?.parentNode?.removeChild(el)\n continue\n }\n\n // Loop through the element's attributes and remove those that are not in the whitelist\n Array.from(el.attributes).forEach((attr) => {\n const name = attr.name.toLowerCase()\n if (!ATTR_WHITELIST.includes(name) || (name === 'href' && !isSafeURL(attr.value))) {\n el.removeAttribute(attr.name)\n }\n })\n\n if (el.hasAttribute('style')) sanitizeStyle(el as HTMLElement)\n\n // Links opening a new tab must not get a handle on the host page (reverse tabnabbing)\n if (el.hasAttribute('target')) el.setAttribute('rel', 'noopener noreferrer')\n }\n\n return doc.body.innerHTML\n}\n\nconst SafeHTMLComponent = ({ html }: { html: string }) => {\n const sanitizedHTML = sanitizeHTML(html)\n\n return <div dangerouslySetInnerHTML={{ __html: sanitizedHTML }} />\n}\n\nexport default SafeHTMLComponent\n"],"names":["_jsx"],"mappings":";;AAEA,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;AACzC,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;AACzD,MAAM,sBAAsB,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAA;AAC7D,MAAM,wBAAwB,GAAG,CAAC,OAAO,CAAC,CAAA;AAE1C;AACA;AACA,SAAS,SAAS,CAAC,KAAa,EAAA;AAC9B,IAAA,IAAI;AACF,QAAA,OAAO,sBAAsB,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC;IACvF;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,KAAK;IACd;AACF;AAEA;AACA,SAAS,aAAa,CAAC,EAAe,EAAA;AACpC,IAAA,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE;IACpB,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACxC,QAAA,IAAI,CAAC,wBAAwB,CAAC,QAAQ,CAAC,QAAQ,CAAC;AAAE,YAAA,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC;IAClF;IACA,IAAI,CAAC,KAAK,CAAC,MAAM;AAAE,QAAA,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC;AAChD;AAEA;AACA,SAAS,YAAY,CAAC,IAAY,EAAA;IAChC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,SAAS,KAAK,WAAW;AAAE,QAAA,OAAO,EAAE;AAEhF,IAAA,MAAM,GAAG,GAAG,IAAI,SAAS,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,WAAW,CAAC;IAC9D,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC;AAE/C,IAAA,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE;;AAEzB,QAAA,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE;AACrD,YAAA,EAAE,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC;YAC/B;QACF;;AAGA,QAAA,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,KAAI;YACzC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;YACpC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE;AACjF,gBAAA,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;YAC/B;AACF,QAAA,CAAC,CAAC;AAEF,QAAA,IAAI,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC;YAAE,aAAa,CAAC,EAAiB,CAAC;;AAG9D,QAAA,IAAI,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC;AAAE,YAAA,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,qBAAqB,CAAC;IAC9E;AAEA,IAAA,OAAO,GAAG,CAAC,IAAI,CAAC,SAAS;AAC3B;AAEA,MAAM,iBAAiB,GAAG,CAAC,EAAE,IAAI,EAAoB,KAAI;AACvD,IAAA,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,CAAC;IAExC,OAAOA,GAAA,CAAA,KAAA,EAAA,EAAK,uBAAuB,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,EAAA,CAAI;AACpE;;;;"}
|