-
Notifications
You must be signed in to change notification settings - Fork 0
/
dominatrixss.js
95 lines (72 loc) · 3.85 KB
/
dominatrixss.js
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
const toDomContentLoaded = performance.now();
var original = document.createElement;
var array = new Uint32Array(1);
window.crypto.getRandomValues(array);
// (function hook) the document.createElement() function is overridden.
document.createElement = function (tag) {
// call the function (createElement)...
// from original document object. This needs to work for all tags,
// so we createElement regardless of tag
var element = original.call(document, tag);
// only for script tags should a nonce value be set.
if (tag.toLowerCase() === 'script') {
element.setAttribute("nonce", array[0]);
// element.setAttribute("nonceTest", (array[0] + 1).toString());
}
return element;
};
function afterDOMloaded() {
var meta = document.createElement('meta');
meta.httpEquiv = 'Content-Security-Policy';
// we need to enable unsafe-eval so we can rewrite the static inline event handlers to external scripta
meta.content= "script-src 'self' 'unsafe-inline' 'unsafe-eval' " + "'nonce-" + array[0].toString() + "' *; worker-src blob: 'self' *;";
document.getElementsByTagName('head')[0].appendChild(meta);
// search by wildcard tag...should grab all nodes
var tag = "*";
var tags = document.getElementsByTagName(tag);
// console.log(tags);
for (var i=0; i<tags.length; i++) {
// we want to see all the attribute names of each node...
// this will allow us to tell if a given attribute is an event handler...
var attributeNames = tags[i].getAttributeNames();
var eventHandlerIndicies = [];
var eventType = [];
// populate array of indicies saving names of event handlers
// specific to current DOM element
for (j = 0; j < attributeNames.length; j++) {
// if (attributeNames[j].includes('on')) {
var attributeNameLength = attributeNames[j].length;
// check to ensure "onXXXX" is the format of the inline eventhandler
// in other words, the eventhandler should start with 'on'
// and should be greater than 2 in length.
if (attributeNames[j][0] == 'o' && attributeNames[j][1] == "n" && attributeNameLength > 2) {
eventHandlerIndicies.push(j);
eventType.push(attributeNames[j].slice(2));
}
}
// We need to loop through all attributes that are infact
// inline event handlers
for (z = 0; z < eventHandlerIndicies.length; z ++) {
var handler = attributeNames[eventHandlerIndicies[z]];
// console.log(handler);
var inlineString = tags[i].getAttribute(handler);
if (inlineString && typeof inlineString == "string") {
//create handler function
var fn = new Function(inlineString)
//actually add the eventListener to the tag
tags[i].addEventListener(eventType[z], fn, false);
//remove the inline handler
tags[i].removeAttribute(handler,0);
}
}
}
// Second action...assigning nonce
meta.setAttribute("http-equiv", "Content-Security-Policy");
meta.setAttribute("content", "script-src 'self' 'unsafe-inline' " + "'nonce-" + array[0].toString() + "' " + "*; worker-src blob: 'self' *;")
}
window.addEventListener('DOMContentLoaded', (event) => {
const domContentLoadedPoint = performance.now();
let timeToDomContentLoaded = domContentLoadedPoint - toDomContentLoaded;
console.log("Time to DOMContentLoaded: " + timeToDomContentLoaded + ": " + window.location + ": " + "test");
afterDOMloaded();
});