Spaces:
Build error
Build error
fix: abuse of flooding elements
Browse files
backend/functions/src/services/puppeteer.ts
CHANGED
|
@@ -50,6 +50,7 @@ export interface PageSnapshot {
|
|
| 50 |
imgs?: ImgBrief[];
|
| 51 |
pdfs?: string[];
|
| 52 |
maxElemDepth?: number;
|
|
|
|
| 53 |
childFrames?: PageSnapshot[];
|
| 54 |
}
|
| 55 |
|
|
@@ -117,14 +118,21 @@ function briefPDFs() {
|
|
| 117 |
return x.src === 'about:blank' ? document.location.href : x.src;
|
| 118 |
});
|
| 119 |
}
|
| 120 |
-
function
|
| 121 |
let maxDepth = 0;
|
| 122 |
let currentDepth = 0;
|
|
|
|
| 123 |
|
| 124 |
-
const treeWalker = document.createTreeWalker(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
|
| 126 |
while (true) {
|
| 127 |
maxDepth = Math.max(maxDepth, currentDepth);
|
|
|
|
| 128 |
|
| 129 |
if (treeWalker.firstChild()) {
|
| 130 |
currentDepth++;
|
|
@@ -140,7 +148,10 @@ function getMaxDepthUsingTreeWalker(root) {
|
|
| 140 |
}
|
| 141 |
}
|
| 142 |
|
| 143 |
-
return
|
|
|
|
|
|
|
|
|
|
| 144 |
}
|
| 145 |
|
| 146 |
function giveSnapshot(stopActiveSnapshot) {
|
|
@@ -153,7 +164,7 @@ function giveSnapshot(stopActiveSnapshot) {
|
|
| 153 |
} catch (err) {
|
| 154 |
void 0;
|
| 155 |
}
|
| 156 |
-
|
| 157 |
const r = {
|
| 158 |
title: document.title,
|
| 159 |
href: document.location.href,
|
|
@@ -162,7 +173,8 @@ function giveSnapshot(stopActiveSnapshot) {
|
|
| 162 |
parsed: parsed,
|
| 163 |
imgs: [],
|
| 164 |
pdfs: briefPDFs(),
|
| 165 |
-
maxElemDepth:
|
|
|
|
| 166 |
};
|
| 167 |
if (parsed && parsed.content) {
|
| 168 |
const elem = document.createElement('div');
|
|
@@ -478,6 +490,10 @@ document.addEventListener('load', handlePageLoad);
|
|
| 478 |
page.emit('abuse', { url, page, sn, reason: `DoS attack suspected: DOM tree too deep` });
|
| 479 |
return;
|
| 480 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 481 |
snapshot = s;
|
| 482 |
nextSnapshotDeferred.resolve(s);
|
| 483 |
nextSnapshotDeferred = Defer();
|
|
|
|
| 50 |
imgs?: ImgBrief[];
|
| 51 |
pdfs?: string[];
|
| 52 |
maxElemDepth?: number;
|
| 53 |
+
elemCount?: number;
|
| 54 |
childFrames?: PageSnapshot[];
|
| 55 |
}
|
| 56 |
|
|
|
|
| 118 |
return x.src === 'about:blank' ? document.location.href : x.src;
|
| 119 |
});
|
| 120 |
}
|
| 121 |
+
function getMaxDepthAndCountUsingTreeWalker(root) {
|
| 122 |
let maxDepth = 0;
|
| 123 |
let currentDepth = 0;
|
| 124 |
+
let elementCount = 0;
|
| 125 |
|
| 126 |
+
const treeWalker = document.createTreeWalker(
|
| 127 |
+
root,
|
| 128 |
+
NodeFilter.SHOW_ELEMENT,
|
| 129 |
+
(node) => (node.nodeName.toLowerCase() === 'svg') ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT,
|
| 130 |
+
false
|
| 131 |
+
);
|
| 132 |
|
| 133 |
while (true) {
|
| 134 |
maxDepth = Math.max(maxDepth, currentDepth);
|
| 135 |
+
elementCount++; // Increment the count for the current node
|
| 136 |
|
| 137 |
if (treeWalker.firstChild()) {
|
| 138 |
currentDepth++;
|
|
|
|
| 148 |
}
|
| 149 |
}
|
| 150 |
|
| 151 |
+
return {
|
| 152 |
+
maxDepth: maxDepth + 1,
|
| 153 |
+
elementCount: elementCount
|
| 154 |
+
};
|
| 155 |
}
|
| 156 |
|
| 157 |
function giveSnapshot(stopActiveSnapshot) {
|
|
|
|
| 164 |
} catch (err) {
|
| 165 |
void 0;
|
| 166 |
}
|
| 167 |
+
const domAnalysis = getMaxDepthAndCountUsingTreeWalker(document.documentElement);
|
| 168 |
const r = {
|
| 169 |
title: document.title,
|
| 170 |
href: document.location.href,
|
|
|
|
| 173 |
parsed: parsed,
|
| 174 |
imgs: [],
|
| 175 |
pdfs: briefPDFs(),
|
| 176 |
+
maxElemDepth: domAnalysis.maxDepth,
|
| 177 |
+
elemCount: domAnalysis.elementCount,
|
| 178 |
};
|
| 179 |
if (parsed && parsed.content) {
|
| 180 |
const elem = document.createElement('div');
|
|
|
|
| 490 |
page.emit('abuse', { url, page, sn, reason: `DoS attack suspected: DOM tree too deep` });
|
| 491 |
return;
|
| 492 |
}
|
| 493 |
+
if (s?.elemCount && s.elemCount > 15_000) {
|
| 494 |
+
page.emit('abuse', { url, page, sn, reason: `DoS attack suspected: too many DOM elements` });
|
| 495 |
+
return;
|
| 496 |
+
}
|
| 497 |
snapshot = s;
|
| 498 |
nextSnapshotDeferred.resolve(s);
|
| 499 |
nextSnapshotDeferred = Defer();
|