-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsnapshot.content.js
More file actions
48 lines (42 loc) · 1.45 KB
/
snapshot.content.js
File metadata and controls
48 lines (42 loc) · 1.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// snapshot.content.js
// Returns a sanitized HTML snapshot when asked.
// - strips <script>, on* event handlers, javascript: URLs, and meta refresh.
function sanitizeDocument() {
const root = document.documentElement.cloneNode(true);
// Remove scripts
root.querySelectorAll('script').forEach(s => s.remove());
// Remove meta refresh
root.querySelectorAll('meta[http-equiv]').forEach(m => {
const v = (m.getAttribute('http-equiv') || '').toLowerCase();
if (v === 'refresh') m.remove();
});
// Remove event handlers + dangerous URLs
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
const toFix = [];
while (walker.nextNode()) toFix.push(walker.currentNode);
for (const el of toFix) {
// remove on* attributes
[...el.attributes].forEach(attr => {
const n = attr.name.toLowerCase();
if (n.startsWith('on')) el.removeAttribute(attr.name);
if (n === 'href' || n === 'xlink:href') {
const val = (attr.value || '').trim().toLowerCase();
if (val.startsWith('javascript:')) el.setAttribute(attr.name, '#');
}
});
}
// Prefer readable charset meta
let html = '<!doctype html>\n' + root.outerHTML;
return html;
}
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg?.type === 'uvcs.snapshot.request') {
try {
const html = sanitizeDocument();
sendResponse(html);
} catch (e) {
sendResponse('');
}
return true;
}
});