@anonympins/fingerprint 0.7.5 → 0.8.1
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/CHANGELOG.md +57 -0
- package/README.md +1 -1
- package/package.json +3 -2
- package/public/anonympins-bot-mitigation-pow.zip +0 -0
- package/src/js/asn-lookup.js +223 -0
- package/src/js/fingerprint.client.js +1784 -1772
- package/src/js/fingerprint.client.obfuscated.js +1 -1
- package/src/js/fingerprint.js +236 -40
- package/src/js/fingerprint.utils.js +252 -2
- package/src/js/pow.worker.js +2 -2
- package/src/js/tests/asn-lookup.test.js +57 -0
- package/src/js/tests/cross_parity.test.js +3 -3
- package/src/js/tests/dns-circuit-breaker.test.js +6 -6
- package/src/js/tests/fingerprint.builder.test.js +76 -78
- package/src/js/tests/fingerprint.client.test.js +16 -17
- package/src/js/tests/fingerprint.test.js +19 -12
- package/src/js/tests/ja3AnomalyDetector.test.js +135 -136
- package/src/js/tests/library.test.js +94 -95
- package/src/js/tests/obfuscation.test.js +8 -8
- package/src/js/tests/quicFingerprint.test.js +47 -0
- package/src/js/tests/tcpFingerprint.test.js +4 -4
- package/src/js/upow-model-task.js +155 -112
- package/src/php/AsnLookupEngine.php +173 -0
- package/src/php/Challenge/ChallengeUtils.php +430 -117
- package/src/php/Config/SecurityProfiles.php +75 -62
- package/src/php/DirectFingerprint.php +80 -13
- package/src/php/FingerprintBuilder.php +13 -13
- package/src/php/FingerprintClient.php +6 -6
- package/src/php/FingerprintEngine.php +2141 -1837
- package/src/php/Ja3AnomalyDetector.php +22 -22
- package/src/php/NetworkProfile.php +68 -0
- package/src/php/Optimization/FunctionRegistry.php +4 -4
- package/src/php/Optimization/Optimization.php +6 -6
- package/src/php/ProblemManager.php +12 -2
- package/src/php/RequestContext.php +11 -11
- package/src/php/Store/InMemoryStore.php +96 -66
- package/src/php/Store/MongoDbStore.php +2 -2
- package/src/php/Store/RedisStore.php +1 -1
- package/src/php/Store/StoreManager.php +48 -35
- package/src/php/Tests/AsnLookupTest.php +61 -0
- package/src/php/Tests/ChallengeUtilsTest.php +31 -0
- package/src/php/Tests/DnsCircuitBreakerTest.php +105 -105
- package/src/php/Tests/FingerprintClientTest.php +70 -70
- package/src/php/Tests/FingerprintEngineTest.php +4 -2
- package/src/php/Tests/PowTest.php +37 -39
- package/src/php/Tests/QuicFingerprintTest.php +115 -53
- package/src/php/Tests/ThreatIntelTest.php +2 -2
- package/src/php/Utils/BigInt.php +202 -202
- package/src/php/Utils/BlockList.php +13 -13
- package/src/php/Utils/Env.php +7 -2
- package/src/php/Utils/Logger.php +19 -1
- package/src/php/Utils/MaliciousPatterns.php +6 -6
- package/src/php/Utils/MetricsManager.php +209 -209
- package/src/php/Utils/RequestUtils.php +348 -18
- package/src/php/Utils/TLSClientHelloParser.php +385 -369
- package/src/php/WordPress/WpDbStore.php +34 -7
- package/src/php/WordPress/anonympins-bot-mitigation-pow.php +1222 -0
- package/src/php/WordPress/fingerprint-anti-bot.php +0 -559
- package/src/php/WordPress/languages/anonympins-bot-mitigation-pow-fr_FR.mo +0 -0
- package/src/php/WordPress/languages/anonympins-bot-mitigation-pow-fr_FR.po +232 -0
- package/src/php/WordPress/languages/fingerprint-wordpress-de_DE.mo +0 -0
- package/src/php/WordPress/languages/fingerprint-wordpress-de_DE.po +297 -261
- package/src/php/WordPress/languages/fingerprint-wordpress-fr_FR.mo +0 -0
- package/src/php/WordPress/languages/fingerprint-wordpress-fr_FR.po +348 -267
- package/src/php/WordPress/package.php +88 -99
- package/src/php/WordPress/readme.txt +28 -6
- package/src/php/bin/auto-tune.php +1 -1
- package/public/fingerprint-anti-bot.zip +0 -0
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
declare(strict_types=1);
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Automated packaging script for the WordPress plugin.
|
|
7
|
+
* Copies PHP engine classes, JS assets, and creates an installation-ready ZIP archive.
|
|
8
8
|
*
|
|
9
9
|
* Usage:
|
|
10
10
|
* php src/php/WordPress/package.php
|
|
@@ -20,13 +20,13 @@ $phpSrcDir = $rootDir . '/src/php';
|
|
|
20
20
|
$jsSrcDir = $rootDir . '/src/js';
|
|
21
21
|
$wpDir = $phpSrcDir . '/WordPress';
|
|
22
22
|
$distDir = $rootDir . '/public';
|
|
23
|
-
$pluginSlug = '
|
|
23
|
+
$pluginSlug = 'anonympins-bot-mitigation-pow';
|
|
24
24
|
$buildDir = $distDir . '/' . $pluginSlug;
|
|
25
25
|
$zipFile = $distDir . '/' . $pluginSlug . '.zip';
|
|
26
26
|
|
|
27
|
-
echo "==>
|
|
27
|
+
echo "==> Packaging WordPress plugin...\n";
|
|
28
28
|
|
|
29
|
-
// 1.
|
|
29
|
+
// 1. Clean previous build directory
|
|
30
30
|
if (is_dir($buildDir)) {
|
|
31
31
|
$iterator = new RecursiveIteratorIterator(
|
|
32
32
|
new RecursiveDirectoryIterator($buildDir, FilesystemIterator::SKIP_DOTS),
|
|
@@ -44,115 +44,104 @@ if (file_exists($zipFile)) {
|
|
|
44
44
|
@mkdir($buildDir . '/src', 0777, true);
|
|
45
45
|
@mkdir($buildDir . '/assets', 0777, true);
|
|
46
46
|
@mkdir($buildDir . '/languages', 0777, true);
|
|
47
|
+
@mkdir($buildDir . '/config', 0777, true);
|
|
48
|
+
|
|
49
|
+
// 2. Copy main WordPress plugin files
|
|
50
|
+
copy($wpDir . '/anonympins-bot-mitigation-pow.php', $buildDir . '/anonympins-bot-mitigation-pow.php');
|
|
51
|
+
copy($wpDir . '/WpDbStore.php', $buildDir . '/WpDbStore.php');
|
|
52
|
+
if (file_exists($wpDir . '/readme.txt')) {
|
|
53
|
+
copy($wpDir . '/readme.txt', $buildDir . '/readme.txt');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 2.b Compile and copy language files (PO -> MO)
|
|
57
|
+
$languagesDir = $wpDir . '/languages';
|
|
58
|
+
if (is_dir($languagesDir)) {
|
|
59
|
+
$poFiles = glob($languagesDir . '/*.po') ?: [];
|
|
60
|
+
foreach ($poFiles as $poFile) {
|
|
61
|
+
$filename = basename($poFile);
|
|
62
|
+
copy($poFile, $buildDir . '/languages/' . $filename);
|
|
63
|
+
|
|
64
|
+
$moFile = preg_replace('/\.po$/', '.mo', $poFile);
|
|
65
|
+
// Compile PO to binary MO if missing or outdated
|
|
66
|
+
if (!file_exists($moFile) || filemtime($poFile) > filemtime($moFile)) {
|
|
67
|
+
compilePoToMo($poFile, $moFile);
|
|
68
|
+
}
|
|
69
|
+
if (file_exists($moFile)) {
|
|
70
|
+
copy($moFile, $buildDir . '/languages/' . basename($moFile));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
47
74
|
|
|
48
75
|
/**
|
|
49
|
-
*
|
|
76
|
+
* Minimal native PHP PO -> binary gettext MO compiler
|
|
50
77
|
*/
|
|
51
|
-
function compilePoToMo(string $
|
|
52
|
-
|
|
53
|
-
$
|
|
54
|
-
if ($content
|
|
55
|
-
|
|
78
|
+
function compilePoToMo(string $poPath, string $moPath): void {
|
|
79
|
+
$content = (string)file_get_contents($poPath);
|
|
80
|
+
$pattern = '/msgid\s+("(?:[^"\\\\]|\\\\.)*")\s+msgstr\s+("(?:[^"\\\\]|\\\\.)*")/s';
|
|
81
|
+
if (!preg_match_all($pattern, $content, $matches, PREG_SET_ORDER)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
56
84
|
$entries = [];
|
|
57
|
-
$
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
foreach ($lines as $line) {
|
|
63
|
-
$line = trim($line);
|
|
64
|
-
if ($line === '' || str_starts_with($line, '#')) continue;
|
|
65
|
-
if (preg_match('/^msgid\s+"(.*)"$/', $line, $m)) {
|
|
66
|
-
if ($currentMsgId !== null && $currentMsgStr !== null) {
|
|
67
|
-
$entries[$currentMsgId] = $currentMsgStr;
|
|
68
|
-
}
|
|
69
|
-
$currentMsgId = stripcslashes($m[1]);
|
|
70
|
-
$currentMsgStr = null;
|
|
71
|
-
$state = 'msgid';
|
|
72
|
-
} elseif (preg_match('/^msgstr\s+"(.*)"$/', $line, $m)) {
|
|
73
|
-
$currentMsgStr = stripcslashes($m[1]);
|
|
74
|
-
$state = 'msgstr';
|
|
75
|
-
} elseif (preg_match('/^"(.*)"$/', $line, $m)) {
|
|
76
|
-
if ($state === 'msgid') {
|
|
77
|
-
$currentMsgId .= stripcslashes($m[1]);
|
|
78
|
-
} elseif ($state === 'msgstr') {
|
|
79
|
-
$currentMsgStr .= stripcslashes($m[1]);
|
|
80
|
-
}
|
|
85
|
+
foreach ($matches as $m) {
|
|
86
|
+
$orig = stripcslashes(substr($m[1], 1, -1));
|
|
87
|
+
$trans = stripcslashes(substr($m[2], 1, -1));
|
|
88
|
+
if ($orig !== '' && $trans !== '') {
|
|
89
|
+
$entries[$orig] = $trans;
|
|
81
90
|
}
|
|
82
91
|
}
|
|
83
|
-
if ($currentMsgId !== null && $currentMsgStr !== null) {
|
|
84
|
-
$entries[$currentMsgId] = $currentMsgStr;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
92
|
ksort($entries);
|
|
88
93
|
$count = count($entries);
|
|
89
|
-
$
|
|
90
|
-
$
|
|
91
|
-
$
|
|
92
|
-
$
|
|
93
|
-
|
|
94
|
-
$
|
|
95
|
-
$tablesSize = $count * 8 * 2;
|
|
96
|
-
$curOffset = $headerSize + $tablesSize;
|
|
97
|
-
|
|
94
|
+
$originalsTable = '';
|
|
95
|
+
$translationsTable = '';
|
|
96
|
+
$origOffsets = [];
|
|
97
|
+
$transOffsets = [];
|
|
98
|
+
$headerLength = 28 + ($count * 8) * 2;
|
|
99
|
+
$currentOffset = $headerLength;
|
|
98
100
|
foreach ($entries as $orig => $trans) {
|
|
99
|
-
$
|
|
100
|
-
$
|
|
101
|
-
$originals .= $orig . "\0";
|
|
101
|
+
$origOffsets[] = ['len' => strlen($orig), 'off' => $currentOffset];
|
|
102
|
+
$currentOffset += strlen($orig) + 1;
|
|
102
103
|
}
|
|
103
|
-
|
|
104
|
-
$transOffset = $curOffset + strlen($originals);
|
|
105
104
|
foreach ($entries as $orig => $trans) {
|
|
106
|
-
$
|
|
107
|
-
$
|
|
108
|
-
$translations .= $trans . "\0";
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
$mo = pack('V*',
|
|
112
|
-
0x950412de, // Magic Number
|
|
113
|
-
0, // Revision
|
|
114
|
-
$count, // Number of strings
|
|
115
|
-
28, // Offset of table with original string lengths and offsets
|
|
116
|
-
28 + ($count * 8), // Offset of table with translation string lengths and offsets
|
|
117
|
-
0, 0 // Hash table size and offset
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
foreach ($origTable as $t) {
|
|
121
|
-
$mo .= pack('VV', $t['len'], $t['off']);
|
|
122
|
-
}
|
|
123
|
-
foreach ($transTable as $t) {
|
|
124
|
-
$mo .= pack('VV', $t['len'], $t['off']);
|
|
105
|
+
$transOffsets[] = ['len' => strlen($trans), 'off' => $currentOffset];
|
|
106
|
+
$currentOffset += strlen($trans) + 1;
|
|
125
107
|
}
|
|
126
|
-
$
|
|
127
|
-
|
|
108
|
+
$binary = pack('V7', 0x950412de, 0, $count, 28, 28 + ($count * 8), 0, 0);
|
|
109
|
+
foreach ($origOffsets as $o) { $binary .= pack('V2', $o['len'], $o['off']); }
|
|
110
|
+
foreach ($transOffsets as $t) { $binary .= pack('V2', $t['len'], $t['off']); }
|
|
111
|
+
foreach ($entries as $orig => $trans) { $binary .= $orig . "\0"; }
|
|
112
|
+
foreach ($entries as $orig => $trans) { $binary .= $trans . "\0"; }
|
|
113
|
+
file_put_contents($moPath, $binary);
|
|
128
114
|
}
|
|
129
115
|
|
|
130
|
-
//
|
|
131
|
-
copy($wpDir . '/fingerprint-anti-bot.php', $buildDir . '/fingerprint-anti-bot.php');
|
|
132
|
-
copy($wpDir . '/WpDbStore.php', $buildDir . '/WpDbStore.php');
|
|
133
|
-
if (file_exists($wpDir . '/readme.txt')) {
|
|
134
|
-
copy($wpDir . '/readme.txt', $buildDir . '/readme.txt');
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// 3. Copie des assets clients nécessaires (solveur PoW)
|
|
116
|
+
// 3. Copy required client assets (PoW solver and client bundle without external CDN)
|
|
138
117
|
$solverSource = $jsSrcDir . '/pow.solver.inline.js';
|
|
139
118
|
if (file_exists($solverSource)) {
|
|
140
|
-
|
|
119
|
+
$solverContent = (string)file_get_contents($solverSource);
|
|
120
|
+
// Neutralize remote CDN scripts prohibited by WordPress.org guidelines
|
|
121
|
+
$solverContent = str_replace(
|
|
122
|
+
["'https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js'", "'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js'"],
|
|
123
|
+
["''", "''"],
|
|
124
|
+
$solverContent
|
|
125
|
+
);
|
|
126
|
+
file_put_contents($buildDir . '/assets/pow.solver.inline.js', $solverContent);
|
|
127
|
+
}
|
|
128
|
+
$clientSource = file_exists($jsSrcDir . '/fingerprint.client.obfuscated.js')
|
|
129
|
+
? $jsSrcDir . '/fingerprint.client.obfuscated.js'
|
|
130
|
+
: $jsSrcDir . '/fingerprint.client.js';
|
|
131
|
+
if (file_exists($clientSource)) {
|
|
132
|
+
copy($clientSource, $buildDir . '/assets/fingerprint.client.js');
|
|
141
133
|
}
|
|
142
134
|
|
|
143
|
-
//
|
|
144
|
-
$
|
|
145
|
-
if (is_dir($
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
copy($
|
|
149
|
-
$moTarget = $buildDir . '/languages/' . preg_replace('/\.po$/', '.mo', $baseName);
|
|
150
|
-
compilePoToMo($poFile, $moTarget);
|
|
151
|
-
compilePoToMo($poFile, $langSourceDir . '/' . preg_replace('/\.po$/', '.mo', $baseName));
|
|
135
|
+
// 3.b Copy problem/bot configuration assets
|
|
136
|
+
$configSourceDir = $rootDir . '/config';
|
|
137
|
+
if (is_dir($configSourceDir)) {
|
|
138
|
+
$configFiles = glob($configSourceDir . '/*.json') ?: [];
|
|
139
|
+
foreach ($configFiles as $cfgFile) {
|
|
140
|
+
copy($cfgFile, $buildDir . '/config/' . basename($cfgFile));
|
|
152
141
|
}
|
|
153
142
|
}
|
|
154
143
|
|
|
155
|
-
//
|
|
144
|
+
// 4. Recursively copy PHP library (src/php -> build/src), excluding dev folders
|
|
156
145
|
$excludeDirs = ['WordPress', 'Tests', 'bin'];
|
|
157
146
|
$phpIterator = new RecursiveIteratorIterator(
|
|
158
147
|
new RecursiveDirectoryIterator($phpSrcDir, FilesystemIterator::SKIP_DOTS),
|
|
@@ -177,9 +166,9 @@ foreach ($phpIterator as $item) {
|
|
|
177
166
|
}
|
|
178
167
|
}
|
|
179
168
|
|
|
180
|
-
echo "==>
|
|
169
|
+
echo "==> Files copied to {$buildDir}\n";
|
|
181
170
|
|
|
182
|
-
// 5.
|
|
171
|
+
// 5. Create ZIP archive
|
|
183
172
|
$zip = new ZipArchive();
|
|
184
173
|
if ($zip->open($zipFile, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
|
|
185
174
|
fwrite(STDERR, "Erreur : Impossible de créer le fichier {$zipFile}\n");
|
|
@@ -194,7 +183,7 @@ $distIterator = new RecursiveIteratorIterator(
|
|
|
194
183
|
foreach ($distIterator as $file) {
|
|
195
184
|
if (!$file->isDir()) {
|
|
196
185
|
$filePath = $file->getPathname();
|
|
197
|
-
//
|
|
186
|
+
// Preserve plugin root directory prefix in archive: anonympins-bot-mitigation-pow/...
|
|
198
187
|
$relativePath = $pluginSlug . '/' . substr($filePath, strlen($buildDir) + 1);
|
|
199
188
|
$zip->addFile($filePath, str_replace('\\', '/', $relativePath));
|
|
200
189
|
}
|
|
@@ -216,6 +205,6 @@ function removeDirectory(string $dir): void
|
|
|
216
205
|
$zip->close();
|
|
217
206
|
removeDirectory($buildDir);
|
|
218
207
|
$sizeKb = round(filesize($zipFile) / 1024, 2);
|
|
219
|
-
echo "==>
|
|
220
|
-
echo "
|
|
221
|
-
echo "
|
|
208
|
+
echo "==> ZIP archive generated successfully:\n";
|
|
209
|
+
echo " File: {$zipFile} ({$sizeKb} KB)\n";
|
|
210
|
+
echo " Ready to be installed via wp-admin or deployed to production.\n";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
===
|
|
1
|
+
=== Anonympins Bot Mitigation with Proof-of-Work ===
|
|
2
2
|
Contributors: anonympins
|
|
3
3
|
Tags: bot protection, security, proof of work, firewall, anti scraping
|
|
4
4
|
Requires at least: 5.9
|
|
5
|
-
Tested up to: 7
|
|
5
|
+
Tested up to: 6.7
|
|
6
6
|
Requires PHP: 8.0
|
|
7
|
-
Stable tag: 0.
|
|
7
|
+
Stable tag: 0.8.1
|
|
8
8
|
License: MIT
|
|
9
9
|
License URI: https://opensource.org/licenses/MIT
|
|
10
10
|
|
|
@@ -12,20 +12,22 @@ High-performance client-side anti-bot protection and Proof-of-Work challenge ver
|
|
|
12
12
|
|
|
13
13
|
== Description ==
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Anonympins Bot Mitigation with Proof-of-Work is a high-performance, privacy-friendly bot mitigation engine for WordPress. It combines behavioral telemetry, TLS/HTTP2/QUIC transport inspection (JA3, JA4), passive TCP/IP stack analysis, and asynchronous Proof-of-Work (PoW) verification.
|
|
16
16
|
|
|
17
17
|
= Features =
|
|
18
18
|
* Transparent protection against scrapers, credential stuffers, and inventory scalpers.
|
|
19
19
|
* Multi-layered behavioral analysis (mouse, keystrokes, touch dynamics).
|
|
20
20
|
* Cryptographic Proof-of-Work challenges (CPU and Memory bound) without third-party CAPTCHA cookies or trackers.
|
|
21
21
|
* Prometheus-compatible metrics endpoint for monitoring and observability.
|
|
22
|
+
* Dedicated Sandbox / Dry-Run mode with IP targeting for testing without blocking legitimate traffic.
|
|
22
23
|
* Tailored security profiles for Frontend, Admin Area (wp-login), and REST API endpoints.
|
|
24
|
+
* Real-time suspicion vector inspection via Server-Sent Events (SSE), REST telemetry, and DOM CustomEvents.
|
|
23
25
|
|
|
24
26
|
== Installation ==
|
|
25
27
|
|
|
26
|
-
1. Upload the plugin files to the `/wp-content/plugins/
|
|
28
|
+
1. Upload the plugin files to the `/wp-content/plugins/anonympins-bot-mitigation-pow` directory, or install the plugin through the WordPress plugins screen directly.
|
|
27
29
|
2. Activate the plugin through the 'Plugins' screen in WordPress.
|
|
28
|
-
3. Navigate to **Settings ->
|
|
30
|
+
3. Navigate to **Settings -> Anonympins Bot Mitigation** to review security profiles, threshold adjustments, and Prometheus metrics.
|
|
29
31
|
|
|
30
32
|
== Frequently Asked Questions ==
|
|
31
33
|
|
|
@@ -34,3 +36,23 @@ No. All evaluations, challenges, and validations occur directly on your WordPres
|
|
|
34
36
|
|
|
35
37
|
= Is HTTPS required? =
|
|
36
38
|
HTTPS is strongly recommended. Under unencrypted HTTP, modern browsers disable the Web Cryptography API (`crypto.subtle`), which reduces challenge verification performance.
|
|
39
|
+
|
|
40
|
+
= How do I scrape the Prometheus metrics endpoint? =
|
|
41
|
+
Metrics can be accessed in standard Prometheus text exposition format via:
|
|
42
|
+
1. The REST API endpoint: `GET /wp-json/fingerprint/v1/metrics` (Requires `manage_options` permission or a custom authorization callback hooked into the `fingerprint_metrics_access` filter).
|
|
43
|
+
2. Direct path endpoint: `GET /metrics` (Evaluated in early execution lifecycle; filterable with `fingerprint_metrics_authorization`).
|
|
44
|
+
3. The admin dashboard: **Settings -> Anonympins Bot Mitigation -> Prometheus Stream**.
|
|
45
|
+
|
|
46
|
+
= How can I monitor incoming request suspicion scores in real time? =
|
|
47
|
+
Under **Settings -> Anonympins Bot Mitigation -> Sandbox / Test Mode**, the plugin provides real-time observability interfaces for all challenged visitors across the website:
|
|
48
|
+
|
|
49
|
+
1. **Server-Sent Events (SSE)**:
|
|
50
|
+
`GET /wp-json/fingerprint/v1/sandbox/sse`
|
|
51
|
+
Streams timestamped telemetry objects containing `id`, `timestamp`, `ip`, `uri`, `action`, `suspicionScore`, and `suspicionVector` for every challenged visitor.
|
|
52
|
+
|
|
53
|
+
2. **REST Telemetry Polling**:
|
|
54
|
+
`GET /wp-json/fingerprint/v1/sandbox/telemetry`
|
|
55
|
+
Returns the latest list and evaluated challenge payloads across all visitors in JSON format.
|
|
56
|
+
|
|
57
|
+
3. **Client-side JavaScript event**:
|
|
58
|
+
Every page emits a DOM `CustomEvent('fingerprint:suspicion')` and sets `window.__FINGERPRINT_VECTOR__` when Sandbox mode is active or when an administrator is authenticated.
|
|
@@ -32,7 +32,7 @@ use Anonympins\Fingerprint\Optimization\Optimization;
|
|
|
32
32
|
use Anonympins\Fingerprint\Store\StoreManager;
|
|
33
33
|
use Anonympins\Fingerprint\Utils\RequestUtils;
|
|
34
34
|
|
|
35
|
-
// 1.
|
|
35
|
+
// 1. Retrieve CLI arguments
|
|
36
36
|
$configPath = $argv[1] ?? null;
|
|
37
37
|
if (!$configPath) {
|
|
38
38
|
echo "Usage: php auto-tune.php [path_to_security-config.json]\n";
|
|
Binary file
|