@fanboynz/network-scanner 2.0.66 → 3.0.0
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.
- package/.github/workflows/npm-publish.yml +134 -10
- package/CHANGELOG.md +135 -0
- package/CLAUDE.md +18 -7
- package/README.md +12 -4
- package/lib/adblock-rust.js +23 -18
- package/lib/adblock.js +127 -82
- package/lib/browserexit.js +210 -200
- package/lib/browserhealth.js +84 -60
- package/lib/cdp.js +103 -81
- package/lib/clear_sitedata.js +61 -159
- package/lib/cloudflare.js +579 -409
- package/lib/colorize.js +29 -12
- package/lib/compare.js +16 -8
- package/lib/compress.js +2 -1
- package/lib/curl.js +287 -220
- package/lib/domain-cache.js +87 -40
- package/lib/dry-run.js +137 -194
- package/lib/fingerprint.js +20 -18
- package/lib/flowproxy.js +391 -188
- package/lib/ghost-cursor.js +8 -7
- package/lib/grep.js +248 -171
- package/lib/ignore_similar.js +70 -124
- package/lib/interaction.js +132 -235
- package/lib/nettools.js +309 -87
- package/lib/openvpn_vpn.js +12 -11
- package/lib/output.js +92 -59
- package/lib/post-processing.js +216 -162
- package/lib/redirect.js +46 -30
- package/lib/referrer.js +158 -165
- package/lib/searchstring.js +290 -381
- package/lib/smart-cache.js +141 -91
- package/lib/socks-relay.js +8 -7
- package/lib/spawn-async.js +137 -0
- package/lib/validate_rules.js +188 -176
- package/lib/wireguard_vpn.js +111 -117
- package/nwss.js +740 -156
- package/package.json +4 -4
package/lib/clear_sitedata.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// Handles comprehensive site data clearing via CDP and page-level fallbacks
|
|
3
3
|
// Resolves SecurityError issues with localStorage/sessionStorage access
|
|
4
4
|
|
|
5
|
-
const { formatLogMessage } = require('./colorize');
|
|
5
|
+
const { formatLogMessage, messageColors } = require('./colorize');
|
|
6
|
+
const CLEAR_SITEDATA_TAG = messageColors.processing('[clear_sitedata]');
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Clears site data using CDP (bypasses same-origin restrictions)
|
|
@@ -15,14 +16,23 @@ const { formatLogMessage } = require('./colorize');
|
|
|
15
16
|
async function clearSiteDataViaCDP(page, currentUrl, forceDebug, quickMode = false) {
|
|
16
17
|
let clearDataSession = null;
|
|
17
18
|
const completedOperations = [];
|
|
18
|
-
|
|
19
|
+
|
|
19
20
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
// Capture the timeout-timer ID so we can clear it once the race
|
|
22
|
+
// resolves. Previously the setTimeout fired 10s after the success
|
|
23
|
+
// path completed — reject was swallowed (race already settled)
|
|
24
|
+
// but the timer kept the event loop reference for up to 10s.
|
|
25
|
+
let timeoutTimer;
|
|
26
|
+
const sessionPromise = page.target().createCDPSession();
|
|
27
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
28
|
+
timeoutTimer = setTimeout(() => reject(new Error('CDP session timeout')), 10000);
|
|
29
|
+
if (typeof timeoutTimer.unref === 'function') timeoutTimer.unref();
|
|
30
|
+
});
|
|
31
|
+
try {
|
|
32
|
+
clearDataSession = await Promise.race([sessionPromise, timeoutPromise]);
|
|
33
|
+
} finally {
|
|
34
|
+
clearTimeout(timeoutTimer);
|
|
35
|
+
}
|
|
26
36
|
|
|
27
37
|
const origin = new URL(currentUrl).origin;
|
|
28
38
|
|
|
@@ -38,7 +48,7 @@ async function clearSiteDataViaCDP(page, currentUrl, forceDebug, quickMode = fal
|
|
|
38
48
|
completedOperations.push(op.name);
|
|
39
49
|
} catch (opErr) {
|
|
40
50
|
if (forceDebug) {
|
|
41
|
-
console.log(formatLogMessage('debug',
|
|
51
|
+
console.log(formatLogMessage('debug', `${CLEAR_SITEDATA_TAG} ${op.name} clear failed: ${opErr.message}`));
|
|
42
52
|
}
|
|
43
53
|
}
|
|
44
54
|
}
|
|
@@ -71,7 +81,7 @@ async function clearSiteDataViaCDP(page, currentUrl, forceDebug, quickMode = fal
|
|
|
71
81
|
completedOperations.push(storage.name);
|
|
72
82
|
} catch (individualErr) {
|
|
73
83
|
if (forceDebug) {
|
|
74
|
-
console.log(formatLogMessage('debug',
|
|
84
|
+
console.log(formatLogMessage('debug', `${CLEAR_SITEDATA_TAG} ${storage.name} clear failed: ${individualErr.message}`));
|
|
75
85
|
}
|
|
76
86
|
}
|
|
77
87
|
}
|
|
@@ -79,14 +89,14 @@ async function clearSiteDataViaCDP(page, currentUrl, forceDebug, quickMode = fal
|
|
|
79
89
|
}
|
|
80
90
|
|
|
81
91
|
if (forceDebug && completedOperations.length > 0) {
|
|
82
|
-
console.log(formatLogMessage('debug',
|
|
92
|
+
console.log(formatLogMessage('debug', `${CLEAR_SITEDATA_TAG} CDP cleared: ${completedOperations.join(', ')}`));
|
|
83
93
|
}
|
|
84
94
|
|
|
85
95
|
return { success: completedOperations.length > 0, operations: completedOperations };
|
|
86
96
|
|
|
87
97
|
} catch (cdpErr) {
|
|
88
98
|
if (forceDebug) {
|
|
89
|
-
console.log(formatLogMessage('debug',
|
|
99
|
+
console.log(formatLogMessage('debug', `${CLEAR_SITEDATA_TAG} CDP session failed: ${cdpErr.message}`));
|
|
90
100
|
}
|
|
91
101
|
return { success: false, operations: completedOperations };
|
|
92
102
|
} finally {
|
|
@@ -108,12 +118,21 @@ async function clearSiteDataViaCDP(page, currentUrl, forceDebug, quickMode = fal
|
|
|
108
118
|
*/
|
|
109
119
|
async function clearSiteDataViaPage(page, forceDebug) {
|
|
110
120
|
try {
|
|
111
|
-
|
|
121
|
+
// Page-side body is now async so we can `await` the IndexedDB
|
|
122
|
+
// cleanup chain. Previously it was sync and the indexedDB.databases()
|
|
123
|
+
// promise was fire-and-forget — cleared.push('indexedDB') ran before
|
|
124
|
+
// the deletion actually completed, so callers saw 'indexedDB' in the
|
|
125
|
+
// operations list even though the dbs were still pending deletion
|
|
126
|
+
// when page.evaluate returned.
|
|
127
|
+
const result = await page.evaluate(async () => {
|
|
112
128
|
const cleared = [];
|
|
113
|
-
|
|
129
|
+
|
|
114
130
|
// Test and clear localStorage
|
|
115
131
|
try {
|
|
116
132
|
if (window.localStorage && typeof window.localStorage.setItem === 'function') {
|
|
133
|
+
// setItem+removeItem is a permission probe — throws SecurityError
|
|
134
|
+
// on some origins before we get to clear(). Don't simplify to
|
|
135
|
+
// just clear() unless you want to swallow those errors silently.
|
|
117
136
|
const testKey = '__nwss_access_test__';
|
|
118
137
|
localStorage.setItem(testKey, 'test');
|
|
119
138
|
localStorage.removeItem(testKey);
|
|
@@ -123,8 +142,8 @@ async function clearSiteDataViaPage(page, forceDebug) {
|
|
|
123
142
|
} catch (e) {
|
|
124
143
|
// Security error expected on some sites
|
|
125
144
|
}
|
|
126
|
-
|
|
127
|
-
// Test and clear sessionStorage
|
|
145
|
+
|
|
146
|
+
// Test and clear sessionStorage
|
|
128
147
|
try {
|
|
129
148
|
if (window.sessionStorage && typeof window.sessionStorage.setItem === 'function') {
|
|
130
149
|
const testKey = '__nwss_access_test__';
|
|
@@ -136,38 +155,40 @@ async function clearSiteDataViaPage(page, forceDebug) {
|
|
|
136
155
|
} catch (e) {
|
|
137
156
|
// Security error expected on some sites
|
|
138
157
|
}
|
|
139
|
-
|
|
140
|
-
// Clear IndexedDB
|
|
158
|
+
|
|
159
|
+
// Clear IndexedDB — actually wait for the deletion chain to
|
|
160
|
+
// complete before reporting. indexedDB.deleteDatabase returns an
|
|
161
|
+
// IDBRequest (not a Promise), so wrap each in a Promise that
|
|
162
|
+
// resolves on success/error/blocked, then Promise.all.
|
|
141
163
|
try {
|
|
142
164
|
if (window.indexedDB && typeof window.indexedDB.databases === 'function') {
|
|
143
|
-
window.indexedDB.databases()
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
});
|
|
165
|
+
const dbs = await window.indexedDB.databases();
|
|
166
|
+
await Promise.all(dbs.map(db => new Promise((resolve) => {
|
|
167
|
+
if (!db.name) return resolve();
|
|
168
|
+
let req;
|
|
169
|
+
try { req = window.indexedDB.deleteDatabase(db.name); }
|
|
170
|
+
catch (_) { return resolve(); }
|
|
171
|
+
req.onsuccess = () => resolve();
|
|
172
|
+
req.onerror = () => resolve(); // best-effort — don't fail the batch
|
|
173
|
+
req.onblocked = () => resolve(); // another tab has it open; can't wait forever
|
|
174
|
+
})));
|
|
154
175
|
cleared.push('indexedDB');
|
|
155
176
|
}
|
|
156
177
|
} catch (e) {
|
|
157
|
-
// IndexedDB may not be available
|
|
178
|
+
// IndexedDB may not be available, or databases() may reject
|
|
158
179
|
}
|
|
159
|
-
|
|
180
|
+
|
|
160
181
|
return cleared;
|
|
161
182
|
});
|
|
162
183
|
|
|
163
184
|
if (forceDebug && result.length > 0) {
|
|
164
|
-
console.log(formatLogMessage('debug',
|
|
185
|
+
console.log(formatLogMessage('debug', `${CLEAR_SITEDATA_TAG} Page-level cleared: ${result.join(', ')}`));
|
|
165
186
|
}
|
|
166
187
|
|
|
167
188
|
return { success: result.length > 0, operations: result };
|
|
168
189
|
} catch (pageErr) {
|
|
169
190
|
if (forceDebug) {
|
|
170
|
-
console.log(formatLogMessage('debug',
|
|
191
|
+
console.log(formatLogMessage('debug', `${CLEAR_SITEDATA_TAG} Page evaluation failed: ${pageErr.message}`));
|
|
171
192
|
}
|
|
172
193
|
return { success: false, operations: [] };
|
|
173
194
|
}
|
|
@@ -216,132 +237,13 @@ async function clearSiteData(page, currentUrl, forceDebug, quickMode = false) {
|
|
|
216
237
|
};
|
|
217
238
|
}
|
|
218
239
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
*/
|
|
227
|
-
async function clearSiteDataEnhanced(page, currentUrl, forceDebug) {
|
|
228
|
-
let clearDataSession = null;
|
|
229
|
-
const completedOperations = [];
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
clearDataSession = await Promise.race([
|
|
233
|
-
page.target().createCDPSession(),
|
|
234
|
-
new Promise((_, reject) =>
|
|
235
|
-
setTimeout(() => reject(new Error('Enhanced CDP session timeout')), 15000)
|
|
236
|
-
)
|
|
237
|
-
]);
|
|
238
|
-
|
|
239
|
-
const origin = new URL(currentUrl).origin;
|
|
240
|
-
|
|
241
|
-
// Enhanced clearing operations
|
|
242
|
-
const enhancedOperations = [
|
|
243
|
-
// Network layer
|
|
244
|
-
{ cmd: 'Network.clearBrowserCookies', name: 'cookies' },
|
|
245
|
-
{ cmd: 'Network.clearBrowserCache', name: 'cache' },
|
|
246
|
-
|
|
247
|
-
// Storage layer - comprehensive
|
|
248
|
-
{
|
|
249
|
-
cmd: 'Storage.clearDataForOrigin',
|
|
250
|
-
params: { origin, storageTypes: 'all' },
|
|
251
|
-
name: 'all_storage'
|
|
252
|
-
},
|
|
253
|
-
|
|
254
|
-
// Runtime layer
|
|
255
|
-
{ cmd: 'Runtime.discardConsoleEntries', name: 'console' },
|
|
256
|
-
|
|
257
|
-
// Security layer
|
|
258
|
-
{ cmd: 'Security.disable', name: 'security_reset' }
|
|
259
|
-
];
|
|
260
|
-
|
|
261
|
-
for (const op of enhancedOperations) {
|
|
262
|
-
try {
|
|
263
|
-
if (op.params) {
|
|
264
|
-
await clearDataSession.send(op.cmd, op.params);
|
|
265
|
-
} else {
|
|
266
|
-
await clearDataSession.send(op.cmd);
|
|
267
|
-
}
|
|
268
|
-
completedOperations.push(op.name);
|
|
269
|
-
} catch (opErr) {
|
|
270
|
-
if (forceDebug) {
|
|
271
|
-
console.log(formatLogMessage('debug', `[clear_sitedata_enhanced] ${op.name} failed: ${opErr.message}`));
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// For storage operations, try individual fallbacks
|
|
275
|
-
if (op.name === 'all_storage') {
|
|
276
|
-
const individualTypes = ['local_storage', 'session_storage', 'indexeddb', 'websql', 'service_workers'];
|
|
277
|
-
for (const type of individualTypes) {
|
|
278
|
-
try {
|
|
279
|
-
await clearDataSession.send('Storage.clearDataForOrigin', {
|
|
280
|
-
origin,
|
|
281
|
-
storageTypes: type
|
|
282
|
-
});
|
|
283
|
-
completedOperations.push(type);
|
|
284
|
-
} catch (individualErr) {
|
|
285
|
-
// Continue trying other types
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// Additional DOM cleanup via page evaluation
|
|
293
|
-
try {
|
|
294
|
-
await page.evaluate(() => {
|
|
295
|
-
// Clear any cached DOM queries
|
|
296
|
-
if (window.document && document.querySelectorAll) {
|
|
297
|
-
// Force garbage collection of cached selectors
|
|
298
|
-
const div = document.createElement('div');
|
|
299
|
-
document.body.appendChild(div);
|
|
300
|
-
document.body.removeChild(div);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// Clear performance entries
|
|
304
|
-
if (window.performance && performance.clearMarks) {
|
|
305
|
-
performance.clearMarks();
|
|
306
|
-
performance.clearMeasures();
|
|
307
|
-
}
|
|
308
|
-
});
|
|
309
|
-
completedOperations.push('dom_cleanup');
|
|
310
|
-
} catch (domErr) {
|
|
311
|
-
if (forceDebug) {
|
|
312
|
-
console.log(formatLogMessage('debug', `[clear_sitedata_enhanced] DOM cleanup failed: ${domErr.message}`));
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
if (forceDebug && completedOperations.length > 0) {
|
|
317
|
-
console.log(formatLogMessage('debug', `[clear_sitedata_enhanced] Cleared: ${completedOperations.join(', ')}`));
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
return {
|
|
321
|
-
success: completedOperations.length > 0,
|
|
322
|
-
operations: completedOperations,
|
|
323
|
-
method: 'enhanced_CDP'
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
} catch (enhancedErr) {
|
|
327
|
-
if (forceDebug) {
|
|
328
|
-
console.log(formatLogMessage('debug', `[clear_sitedata_enhanced] Failed: ${enhancedErr.message}`));
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Fallback to regular clearing
|
|
332
|
-
return await clearSiteData(page, currentUrl, forceDebug, false);
|
|
333
|
-
|
|
334
|
-
} finally {
|
|
335
|
-
if (clearDataSession) {
|
|
336
|
-
try {
|
|
337
|
-
await clearDataSession.detach();
|
|
338
|
-
} catch (detachErr) {
|
|
339
|
-
// Ignore detach errors
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
240
|
+
// Public surface. clearSiteDataViaCDP / clearSiteDataViaPage are
|
|
241
|
+
// internal helpers but exported for testing / advanced callers.
|
|
242
|
+
// (Previously also defined a clearSiteDataEnhanced function that wasn't
|
|
243
|
+
// even exported and had zero callers anywhere — 117 lines of dead code
|
|
244
|
+
// removed, including a mislabeled "Security.disable" CDP call dressed
|
|
245
|
+
// up as "security_reset" that just disabled the CDP Security domain
|
|
246
|
+
// with no actual security effect.)
|
|
345
247
|
module.exports = {
|
|
346
248
|
clearSiteData,
|
|
347
249
|
clearSiteDataViaCDP,
|