@arcis/node 1.6.1 → 1.6.3
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/README.md +5 -3
- package/dist/_third_party/rate-limit/abstract.d.ts +36 -0
- package/dist/_third_party/rate-limit/abstract.d.ts.map +1 -0
- package/dist/_third_party/rate-limit/bursty.d.ts +21 -0
- package/dist/_third_party/rate-limit/bursty.d.ts.map +1 -0
- package/dist/_third_party/rate-limit/index.d.ts +12 -0
- package/dist/_third_party/rate-limit/index.d.ts.map +1 -0
- package/dist/_third_party/rate-limit/memory-storage.d.ts +28 -0
- package/dist/_third_party/rate-limit/memory-storage.d.ts.map +1 -0
- package/dist/_third_party/rate-limit/memory.d.ts +23 -0
- package/dist/_third_party/rate-limit/memory.d.ts.map +1 -0
- package/dist/_third_party/rate-limit/record.d.ts +11 -0
- package/dist/_third_party/rate-limit/record.d.ts.map +1 -0
- package/dist/_third_party/rate-limit/types.d.ts +39 -0
- package/dist/_third_party/rate-limit/types.d.ts.map +1 -0
- package/dist/astro/index.js +405 -0
- package/dist/astro/index.js.map +1 -1
- package/dist/astro/index.mjs +405 -0
- package/dist/astro/index.mjs.map +1 -1
- package/dist/bun/index.js +405 -0
- package/dist/bun/index.js.map +1 -1
- package/dist/bun/index.mjs +405 -0
- package/dist/bun/index.mjs.map +1 -1
- package/dist/fastify/index.js +405 -0
- package/dist/fastify/index.js.map +1 -1
- package/dist/fastify/index.mjs +405 -0
- package/dist/fastify/index.mjs.map +1 -1
- package/dist/hono/index.js +405 -0
- package/dist/hono/index.js.map +1 -1
- package/dist/hono/index.mjs +405 -0
- package/dist/hono/index.mjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +754 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +754 -6
- package/dist/index.mjs.map +1 -1
- package/dist/koa/index.js +405 -0
- package/dist/koa/index.js.map +1 -1
- package/dist/koa/index.mjs +405 -0
- package/dist/koa/index.mjs.map +1 -1
- package/dist/middleware/brute-force.d.ts +69 -0
- package/dist/middleware/brute-force.d.ts.map +1 -0
- package/dist/middleware/index.js +702 -1
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +702 -1
- package/dist/middleware/index.mjs.map +1 -1
- package/dist/middleware/nestjs.d.ts +50 -1
- package/dist/middleware/nestjs.d.ts.map +1 -1
- package/dist/middleware/protect.d.ts +9 -0
- package/dist/middleware/protect.d.ts.map +1 -1
- package/dist/nestjs/index.js +57 -2
- package/dist/nestjs/index.js.map +1 -1
- package/dist/nestjs/index.mjs +57 -3
- package/dist/nestjs/index.mjs.map +1 -1
- package/dist/nextjs/index.js +405 -0
- package/dist/nextjs/index.js.map +1 -1
- package/dist/nextjs/index.mjs +405 -0
- package/dist/nextjs/index.mjs.map +1 -1
- package/dist/nuxt/index.js +405 -0
- package/dist/nuxt/index.js.map +1 -1
- package/dist/nuxt/index.mjs +405 -0
- package/dist/nuxt/index.mjs.map +1 -1
- package/dist/sanitizers/index.js +2 -1
- package/dist/sanitizers/index.js.map +1 -1
- package/dist/sanitizers/index.mjs +2 -1
- package/dist/sanitizers/index.mjs.map +1 -1
- package/dist/sanitizers/ldap.d.ts.map +1 -1
- package/dist/sanitizers/prompt-injection.d.ts +3 -3
- package/dist/sanitizers/prompt-injection.d.ts.map +1 -1
- package/dist/sveltekit/index.js +405 -0
- package/dist/sveltekit/index.js.map +1 -1
- package/dist/sveltekit/index.mjs +405 -0
- package/dist/sveltekit/index.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -941,9 +941,10 @@ function detectXxe(input) {
|
|
|
941
941
|
// src/sanitizers/ldap.ts
|
|
942
942
|
var LDAP_DETECT_PATTERN = /[*()\\\x00]/;
|
|
943
943
|
var LDAP_INJECTION_PATTERN = /\)\s*\(|\*\s*\)\s*\(/;
|
|
944
|
+
var LDAP_NOT_BYPASS_PATTERN = /\)\s*\(\s*!|&\s*\(\s*!|\|\s*\(\s*!/;
|
|
944
945
|
function detectLdapInjection(input) {
|
|
945
946
|
if (typeof input !== "string") return false;
|
|
946
|
-
return LDAP_DETECT_PATTERN.test(input) || LDAP_INJECTION_PATTERN.test(input);
|
|
947
|
+
return LDAP_DETECT_PATTERN.test(input) || LDAP_INJECTION_PATTERN.test(input) || LDAP_NOT_BYPASS_PATTERN.test(input);
|
|
947
948
|
}
|
|
948
949
|
|
|
949
950
|
// src/sanitizers/xpath.ts
|
|
@@ -8270,6 +8271,411 @@ var bot_patterns_default = [
|
|
|
8270
8271
|
"ZuperlistBot\\/"
|
|
8271
8272
|
],
|
|
8272
8273
|
forbidden: []
|
|
8274
|
+
},
|
|
8275
|
+
{
|
|
8276
|
+
id: "ext-ahrefsbotsiteaudit",
|
|
8277
|
+
name: "ahrefsbotsiteaudit",
|
|
8278
|
+
category: "SEO",
|
|
8279
|
+
patterns: [
|
|
8280
|
+
"Ahrefs(Bot|SiteAudit)"
|
|
8281
|
+
],
|
|
8282
|
+
forbidden: []
|
|
8283
|
+
},
|
|
8284
|
+
{
|
|
8285
|
+
id: "ext-amazonproductdiscovery",
|
|
8286
|
+
name: "amazonproductdiscovery",
|
|
8287
|
+
category: "SEARCH_ENGINE",
|
|
8288
|
+
patterns: [
|
|
8289
|
+
"AmazonProductDiscovery"
|
|
8290
|
+
],
|
|
8291
|
+
forbidden: []
|
|
8292
|
+
},
|
|
8293
|
+
{
|
|
8294
|
+
id: "ext-amazonsellerinitiatedlisting",
|
|
8295
|
+
name: "amazonsellerinitiatedlisting",
|
|
8296
|
+
category: "SEARCH_ENGINE",
|
|
8297
|
+
patterns: [
|
|
8298
|
+
"AmazonSellerInitiatedListing"
|
|
8299
|
+
],
|
|
8300
|
+
forbidden: []
|
|
8301
|
+
},
|
|
8302
|
+
{
|
|
8303
|
+
id: "ext-cclaudebbot",
|
|
8304
|
+
name: "cclaudebbot",
|
|
8305
|
+
category: "GENERIC",
|
|
8306
|
+
patterns: [
|
|
8307
|
+
"[cC]laude[bB]ot"
|
|
8308
|
+
],
|
|
8309
|
+
forbidden: []
|
|
8310
|
+
},
|
|
8311
|
+
{
|
|
8312
|
+
id: "ext-meta-externalagent",
|
|
8313
|
+
name: "meta-externalagent",
|
|
8314
|
+
category: "GENERIC",
|
|
8315
|
+
patterns: [
|
|
8316
|
+
"meta-externalagent\\/"
|
|
8317
|
+
],
|
|
8318
|
+
forbidden: []
|
|
8319
|
+
},
|
|
8320
|
+
{
|
|
8321
|
+
id: "ext-meta-externalfetcher",
|
|
8322
|
+
name: "meta-externalfetcher",
|
|
8323
|
+
category: "GENERIC",
|
|
8324
|
+
patterns: [
|
|
8325
|
+
"meta-externalfetcher\\/"
|
|
8326
|
+
],
|
|
8327
|
+
forbidden: []
|
|
8328
|
+
},
|
|
8329
|
+
{
|
|
8330
|
+
id: "ext-hydrozenio",
|
|
8331
|
+
name: "hydrozenio",
|
|
8332
|
+
category: "MONITORING",
|
|
8333
|
+
patterns: [
|
|
8334
|
+
"Hydrozen\\.io"
|
|
8335
|
+
],
|
|
8336
|
+
forbidden: []
|
|
8337
|
+
},
|
|
8338
|
+
{
|
|
8339
|
+
id: "ext-yextbot",
|
|
8340
|
+
name: "yextbot",
|
|
8341
|
+
category: "SEO",
|
|
8342
|
+
patterns: [
|
|
8343
|
+
"YextBot\\/"
|
|
8344
|
+
],
|
|
8345
|
+
forbidden: []
|
|
8346
|
+
},
|
|
8347
|
+
{
|
|
8348
|
+
id: "ext-datadogsynthetics",
|
|
8349
|
+
name: "datadogsynthetics",
|
|
8350
|
+
category: "MONITORING",
|
|
8351
|
+
patterns: [
|
|
8352
|
+
"DatadogSynthetics"
|
|
8353
|
+
],
|
|
8354
|
+
forbidden: []
|
|
8355
|
+
},
|
|
8356
|
+
{
|
|
8357
|
+
id: "ext-observepoint",
|
|
8358
|
+
name: "observepoint",
|
|
8359
|
+
category: "MONITORING",
|
|
8360
|
+
patterns: [
|
|
8361
|
+
"ObservePoint"
|
|
8362
|
+
],
|
|
8363
|
+
forbidden: []
|
|
8364
|
+
},
|
|
8365
|
+
{
|
|
8366
|
+
id: "ext-checkly",
|
|
8367
|
+
name: "checkly",
|
|
8368
|
+
category: "MONITORING",
|
|
8369
|
+
patterns: [
|
|
8370
|
+
"Checkly"
|
|
8371
|
+
],
|
|
8372
|
+
forbidden: []
|
|
8373
|
+
},
|
|
8374
|
+
{
|
|
8375
|
+
id: "ext-alittleclient",
|
|
8376
|
+
name: "alittleclient",
|
|
8377
|
+
category: "GENERIC",
|
|
8378
|
+
patterns: [
|
|
8379
|
+
"ALittle Client"
|
|
8380
|
+
],
|
|
8381
|
+
forbidden: []
|
|
8382
|
+
},
|
|
8383
|
+
{
|
|
8384
|
+
id: "ext-aliyunsecbot",
|
|
8385
|
+
name: "aliyunsecbot",
|
|
8386
|
+
category: "GENERIC",
|
|
8387
|
+
patterns: [
|
|
8388
|
+
"AliyunSecBot"
|
|
8389
|
+
],
|
|
8390
|
+
forbidden: []
|
|
8391
|
+
},
|
|
8392
|
+
{
|
|
8393
|
+
id: "ext-claude-web",
|
|
8394
|
+
name: "claude-web",
|
|
8395
|
+
category: "GENERIC",
|
|
8396
|
+
patterns: [
|
|
8397
|
+
"Claude-Web"
|
|
8398
|
+
],
|
|
8399
|
+
forbidden: []
|
|
8400
|
+
},
|
|
8401
|
+
{
|
|
8402
|
+
id: "ext-google-extended",
|
|
8403
|
+
name: "google-extended",
|
|
8404
|
+
category: "GENERIC",
|
|
8405
|
+
patterns: [
|
|
8406
|
+
"Google-Extended"
|
|
8407
|
+
],
|
|
8408
|
+
forbidden: []
|
|
8409
|
+
},
|
|
8410
|
+
{
|
|
8411
|
+
id: "ext-serankingbacklinksbot",
|
|
8412
|
+
name: "serankingbacklinksbot",
|
|
8413
|
+
category: "SEO",
|
|
8414
|
+
patterns: [
|
|
8415
|
+
"SERankingBacklinksBot"
|
|
8416
|
+
],
|
|
8417
|
+
forbidden: []
|
|
8418
|
+
},
|
|
8419
|
+
{
|
|
8420
|
+
id: "ext-cmschecker",
|
|
8421
|
+
name: "cmschecker",
|
|
8422
|
+
category: "SEO",
|
|
8423
|
+
patterns: [
|
|
8424
|
+
"CMSChecker"
|
|
8425
|
+
],
|
|
8426
|
+
forbidden: []
|
|
8427
|
+
},
|
|
8428
|
+
{
|
|
8429
|
+
id: "ext-wayback",
|
|
8430
|
+
name: "wayback",
|
|
8431
|
+
category: "GENERIC",
|
|
8432
|
+
patterns: [
|
|
8433
|
+
"Wayback"
|
|
8434
|
+
],
|
|
8435
|
+
forbidden: []
|
|
8436
|
+
},
|
|
8437
|
+
{
|
|
8438
|
+
id: "ext-playwright",
|
|
8439
|
+
name: "playwright",
|
|
8440
|
+
category: "GENERIC",
|
|
8441
|
+
patterns: [
|
|
8442
|
+
"Playwright"
|
|
8443
|
+
],
|
|
8444
|
+
forbidden: []
|
|
8445
|
+
},
|
|
8446
|
+
{
|
|
8447
|
+
id: "ext-puppeteer",
|
|
8448
|
+
name: "puppeteer",
|
|
8449
|
+
category: "GENERIC",
|
|
8450
|
+
patterns: [
|
|
8451
|
+
"Puppeteer"
|
|
8452
|
+
],
|
|
8453
|
+
forbidden: []
|
|
8454
|
+
},
|
|
8455
|
+
{
|
|
8456
|
+
id: "ext-selenium",
|
|
8457
|
+
name: "selenium",
|
|
8458
|
+
category: "GENERIC",
|
|
8459
|
+
patterns: [
|
|
8460
|
+
"Selenium"
|
|
8461
|
+
],
|
|
8462
|
+
forbidden: []
|
|
8463
|
+
},
|
|
8464
|
+
{
|
|
8465
|
+
id: "ext-nikto",
|
|
8466
|
+
name: "nikto",
|
|
8467
|
+
category: "GENERIC",
|
|
8468
|
+
patterns: [
|
|
8469
|
+
"Nikto"
|
|
8470
|
+
],
|
|
8471
|
+
forbidden: []
|
|
8472
|
+
},
|
|
8473
|
+
{
|
|
8474
|
+
id: "ext-sqlmap",
|
|
8475
|
+
name: "sqlmap",
|
|
8476
|
+
category: "GENERIC",
|
|
8477
|
+
patterns: [
|
|
8478
|
+
"sqlmap"
|
|
8479
|
+
],
|
|
8480
|
+
forbidden: []
|
|
8481
|
+
},
|
|
8482
|
+
{
|
|
8483
|
+
id: "ext-zmeu",
|
|
8484
|
+
name: "zmeu",
|
|
8485
|
+
category: "GENERIC",
|
|
8486
|
+
patterns: [
|
|
8487
|
+
"ZmEu"
|
|
8488
|
+
],
|
|
8489
|
+
forbidden: []
|
|
8490
|
+
},
|
|
8491
|
+
{
|
|
8492
|
+
id: "ext-masscan",
|
|
8493
|
+
name: "masscan",
|
|
8494
|
+
category: "GENERIC",
|
|
8495
|
+
patterns: [
|
|
8496
|
+
"masscan"
|
|
8497
|
+
],
|
|
8498
|
+
forbidden: []
|
|
8499
|
+
},
|
|
8500
|
+
{
|
|
8501
|
+
id: "ext-wpscan",
|
|
8502
|
+
name: "wpscan",
|
|
8503
|
+
category: "GENERIC",
|
|
8504
|
+
patterns: [
|
|
8505
|
+
"WPScan"
|
|
8506
|
+
],
|
|
8507
|
+
forbidden: []
|
|
8508
|
+
},
|
|
8509
|
+
{
|
|
8510
|
+
id: "ext-aacunetix",
|
|
8511
|
+
name: "aacunetix",
|
|
8512
|
+
category: "GENERIC",
|
|
8513
|
+
patterns: [
|
|
8514
|
+
"[aA]cunetix"
|
|
8515
|
+
],
|
|
8516
|
+
forbidden: []
|
|
8517
|
+
},
|
|
8518
|
+
{
|
|
8519
|
+
id: "ext-nessus",
|
|
8520
|
+
name: "nessus",
|
|
8521
|
+
category: "GENERIC",
|
|
8522
|
+
patterns: [
|
|
8523
|
+
"Nessus"
|
|
8524
|
+
],
|
|
8525
|
+
forbidden: []
|
|
8526
|
+
},
|
|
8527
|
+
{
|
|
8528
|
+
id: "ext-ddirbbuster",
|
|
8529
|
+
name: "ddirbbuster",
|
|
8530
|
+
category: "GENERIC",
|
|
8531
|
+
patterns: [
|
|
8532
|
+
"[dD]ir[Bb]uster"
|
|
8533
|
+
],
|
|
8534
|
+
forbidden: []
|
|
8535
|
+
},
|
|
8536
|
+
{
|
|
8537
|
+
id: "ext-colly",
|
|
8538
|
+
name: "colly",
|
|
8539
|
+
category: "GENERIC",
|
|
8540
|
+
patterns: [
|
|
8541
|
+
"colly"
|
|
8542
|
+
],
|
|
8543
|
+
forbidden: []
|
|
8544
|
+
},
|
|
8545
|
+
{
|
|
8546
|
+
id: "ext-mmechanize",
|
|
8547
|
+
name: "mmechanize",
|
|
8548
|
+
category: "GENERIC",
|
|
8549
|
+
patterns: [
|
|
8550
|
+
"[mM]echanize"
|
|
8551
|
+
],
|
|
8552
|
+
forbidden: []
|
|
8553
|
+
},
|
|
8554
|
+
{
|
|
8555
|
+
id: "ext-airaiscanning",
|
|
8556
|
+
name: "airaiscanning",
|
|
8557
|
+
category: "GENERIC",
|
|
8558
|
+
patterns: [
|
|
8559
|
+
"air\\.ai\\/scanning"
|
|
8560
|
+
],
|
|
8561
|
+
forbidden: []
|
|
8562
|
+
},
|
|
8563
|
+
{
|
|
8564
|
+
id: "ext-asnriskscorer",
|
|
8565
|
+
name: "asnriskscorer",
|
|
8566
|
+
category: "GENERIC",
|
|
8567
|
+
patterns: [
|
|
8568
|
+
"asnriskscorer"
|
|
8569
|
+
],
|
|
8570
|
+
forbidden: []
|
|
8571
|
+
},
|
|
8572
|
+
{
|
|
8573
|
+
id: "ext-oicrawler",
|
|
8574
|
+
name: "oicrawler",
|
|
8575
|
+
category: "SEARCH_ENGINE",
|
|
8576
|
+
patterns: [
|
|
8577
|
+
"OICrawler"
|
|
8578
|
+
],
|
|
8579
|
+
forbidden: []
|
|
8580
|
+
},
|
|
8581
|
+
{
|
|
8582
|
+
id: "ext-l9scan",
|
|
8583
|
+
name: "l9scan",
|
|
8584
|
+
category: "GENERIC",
|
|
8585
|
+
patterns: [
|
|
8586
|
+
"l9scan"
|
|
8587
|
+
],
|
|
8588
|
+
forbidden: []
|
|
8589
|
+
},
|
|
8590
|
+
{
|
|
8591
|
+
id: "ext-slaccalebot",
|
|
8592
|
+
name: "slaccalebot",
|
|
8593
|
+
category: "SEO",
|
|
8594
|
+
patterns: [
|
|
8595
|
+
"SlaccaleBot"
|
|
8596
|
+
],
|
|
8597
|
+
forbidden: []
|
|
8598
|
+
},
|
|
8599
|
+
{
|
|
8600
|
+
id: "ext-customasynchttpclient",
|
|
8601
|
+
name: "customasynchttpclient",
|
|
8602
|
+
category: "GENERIC",
|
|
8603
|
+
patterns: [
|
|
8604
|
+
"CustomAsyncHttpClient"
|
|
8605
|
+
],
|
|
8606
|
+
forbidden: []
|
|
8607
|
+
},
|
|
8608
|
+
{
|
|
8609
|
+
id: "ext-gemini-deep-research",
|
|
8610
|
+
name: "gemini-deep-research",
|
|
8611
|
+
category: "SEARCH_ENGINE",
|
|
8612
|
+
patterns: [
|
|
8613
|
+
"Gemini-Deep-Research"
|
|
8614
|
+
],
|
|
8615
|
+
forbidden: []
|
|
8616
|
+
},
|
|
8617
|
+
{
|
|
8618
|
+
id: "ext-perplexity-user",
|
|
8619
|
+
name: "perplexity-user",
|
|
8620
|
+
category: "SEARCH_ENGINE",
|
|
8621
|
+
patterns: [
|
|
8622
|
+
"Perplexity-User"
|
|
8623
|
+
],
|
|
8624
|
+
forbidden: []
|
|
8625
|
+
},
|
|
8626
|
+
{
|
|
8627
|
+
id: "ext-perplexityuser",
|
|
8628
|
+
name: "perplexityuser",
|
|
8629
|
+
category: "SEARCH_ENGINE",
|
|
8630
|
+
patterns: [
|
|
8631
|
+
"PerplexityUser"
|
|
8632
|
+
],
|
|
8633
|
+
forbidden: []
|
|
8634
|
+
},
|
|
8635
|
+
{
|
|
8636
|
+
id: "ext-meta-webindexer",
|
|
8637
|
+
name: "meta-webindexer",
|
|
8638
|
+
category: "GENERIC",
|
|
8639
|
+
patterns: [
|
|
8640
|
+
"meta-webindexer"
|
|
8641
|
+
],
|
|
8642
|
+
forbidden: []
|
|
8643
|
+
},
|
|
8644
|
+
{
|
|
8645
|
+
id: "ext-duckassistbot",
|
|
8646
|
+
name: "duckassistbot",
|
|
8647
|
+
category: "SEARCH_ENGINE",
|
|
8648
|
+
patterns: [
|
|
8649
|
+
"DuckAssistBot"
|
|
8650
|
+
],
|
|
8651
|
+
forbidden: []
|
|
8652
|
+
},
|
|
8653
|
+
{
|
|
8654
|
+
id: "ext-mistralai-user",
|
|
8655
|
+
name: "mistralai-user",
|
|
8656
|
+
category: "GENERIC",
|
|
8657
|
+
patterns: [
|
|
8658
|
+
"MistralAI-User"
|
|
8659
|
+
],
|
|
8660
|
+
forbidden: []
|
|
8661
|
+
},
|
|
8662
|
+
{
|
|
8663
|
+
id: "ext-webzio",
|
|
8664
|
+
name: "webzio",
|
|
8665
|
+
category: "SEO",
|
|
8666
|
+
patterns: [
|
|
8667
|
+
"webzio"
|
|
8668
|
+
],
|
|
8669
|
+
forbidden: []
|
|
8670
|
+
},
|
|
8671
|
+
{
|
|
8672
|
+
id: "ext-newsai",
|
|
8673
|
+
name: "newsai",
|
|
8674
|
+
category: "GENERIC",
|
|
8675
|
+
patterns: [
|
|
8676
|
+
"newsai\\/"
|
|
8677
|
+
],
|
|
8678
|
+
forbidden: []
|
|
8273
8679
|
}
|
|
8274
8680
|
];
|
|
8275
8681
|
|
|
@@ -8806,6 +9212,297 @@ function massAssign(options) {
|
|
|
8806
9212
|
};
|
|
8807
9213
|
}
|
|
8808
9214
|
|
|
9215
|
+
// src/_third_party/rate-limit/abstract.ts
|
|
9216
|
+
var AbstractLimiter = class {
|
|
9217
|
+
constructor(opts) {
|
|
9218
|
+
if (!Number.isFinite(opts.points)) {
|
|
9219
|
+
throw new Error("points must be a finite number");
|
|
9220
|
+
}
|
|
9221
|
+
if (!Number.isFinite(opts.duration) || opts.duration < 0) {
|
|
9222
|
+
throw new Error("duration must be a finite, non-negative number");
|
|
9223
|
+
}
|
|
9224
|
+
this._points = opts.points;
|
|
9225
|
+
this._duration = opts.duration;
|
|
9226
|
+
this._blockDuration = typeof opts.blockDuration === "undefined" ? 0 : opts.blockDuration;
|
|
9227
|
+
this._execEvenly = Boolean(opts.execEvenly);
|
|
9228
|
+
this._execEvenlyMinDelayMs = typeof opts.execEvenlyMinDelayMs === "undefined" ? Math.ceil(this._duration * 1e3 / Math.max(this._points, 1)) : opts.execEvenlyMinDelayMs;
|
|
9229
|
+
if (typeof opts.keyPrefix === "undefined") {
|
|
9230
|
+
this._keyPrefix = "arcis";
|
|
9231
|
+
} else if (typeof opts.keyPrefix !== "string") {
|
|
9232
|
+
throw new Error("keyPrefix must be a string");
|
|
9233
|
+
} else {
|
|
9234
|
+
this._keyPrefix = opts.keyPrefix;
|
|
9235
|
+
}
|
|
9236
|
+
}
|
|
9237
|
+
get points() {
|
|
9238
|
+
return this._points;
|
|
9239
|
+
}
|
|
9240
|
+
get duration() {
|
|
9241
|
+
return this._duration;
|
|
9242
|
+
}
|
|
9243
|
+
get msDuration() {
|
|
9244
|
+
return this._duration * 1e3;
|
|
9245
|
+
}
|
|
9246
|
+
get blockDuration() {
|
|
9247
|
+
return this._blockDuration;
|
|
9248
|
+
}
|
|
9249
|
+
get msBlockDuration() {
|
|
9250
|
+
return this._blockDuration * 1e3;
|
|
9251
|
+
}
|
|
9252
|
+
get execEvenly() {
|
|
9253
|
+
return this._execEvenly;
|
|
9254
|
+
}
|
|
9255
|
+
get execEvenlyMinDelayMs() {
|
|
9256
|
+
return this._execEvenlyMinDelayMs;
|
|
9257
|
+
}
|
|
9258
|
+
get keyPrefix() {
|
|
9259
|
+
return this._keyPrefix;
|
|
9260
|
+
}
|
|
9261
|
+
_getKeySecDuration(options = {}) {
|
|
9262
|
+
return typeof options.customDuration === "number" && options.customDuration >= 0 ? options.customDuration : this._duration;
|
|
9263
|
+
}
|
|
9264
|
+
_getKey(key) {
|
|
9265
|
+
return this._keyPrefix.length > 0 ? `${this._keyPrefix}:${key}` : key;
|
|
9266
|
+
}
|
|
9267
|
+
};
|
|
9268
|
+
|
|
9269
|
+
// src/_third_party/rate-limit/types.ts
|
|
9270
|
+
var LimiterResult = class {
|
|
9271
|
+
constructor(remainingPoints = 0, msBeforeNext = 0, consumedPoints = 0, isFirstInDuration = false) {
|
|
9272
|
+
this.remainingPoints = remainingPoints;
|
|
9273
|
+
this.msBeforeNext = msBeforeNext;
|
|
9274
|
+
this.consumedPoints = consumedPoints;
|
|
9275
|
+
this.isFirstInDuration = isFirstInDuration;
|
|
9276
|
+
}
|
|
9277
|
+
};
|
|
9278
|
+
|
|
9279
|
+
// src/_third_party/rate-limit/record.ts
|
|
9280
|
+
var StorageRecord = class {
|
|
9281
|
+
constructor(value, expiresAt, timeoutId = null) {
|
|
9282
|
+
this.value = Math.trunc(value);
|
|
9283
|
+
this.expiresAt = expiresAt;
|
|
9284
|
+
this.timeoutId = timeoutId;
|
|
9285
|
+
}
|
|
9286
|
+
};
|
|
9287
|
+
|
|
9288
|
+
// src/_third_party/rate-limit/memory-storage.ts
|
|
9289
|
+
var MemoryStorage = class {
|
|
9290
|
+
constructor() {
|
|
9291
|
+
this._storage = /* @__PURE__ */ new Map();
|
|
9292
|
+
}
|
|
9293
|
+
/**
|
|
9294
|
+
* Increment the counter for `key` by `value`. If the key has no record
|
|
9295
|
+
* (or its TTL has expired), a new record is created with `durationSec`
|
|
9296
|
+
* lifetime.
|
|
9297
|
+
*/
|
|
9298
|
+
incrby(key, value, durationSec) {
|
|
9299
|
+
const record = this._storage.get(key);
|
|
9300
|
+
if (record) {
|
|
9301
|
+
const msBeforeExpires = record.expiresAt ? record.expiresAt - Date.now() : -1;
|
|
9302
|
+
if (!record.expiresAt || msBeforeExpires > 0) {
|
|
9303
|
+
record.value = record.value + value;
|
|
9304
|
+
return new LimiterResult(0, msBeforeExpires, record.value, false);
|
|
9305
|
+
}
|
|
9306
|
+
return this.set(key, value, durationSec);
|
|
9307
|
+
}
|
|
9308
|
+
return this.set(key, value, durationSec);
|
|
9309
|
+
}
|
|
9310
|
+
/**
|
|
9311
|
+
* Write the counter for `key` to `value`, replacing any existing
|
|
9312
|
+
* record. `durationSec` of 0 means "never expires".
|
|
9313
|
+
*/
|
|
9314
|
+
set(key, value, durationSec) {
|
|
9315
|
+
const durationMs = durationSec * 1e3;
|
|
9316
|
+
const existing = this._storage.get(key);
|
|
9317
|
+
if (existing && existing.timeoutId) {
|
|
9318
|
+
clearTimeout(existing.timeoutId);
|
|
9319
|
+
}
|
|
9320
|
+
const record = new StorageRecord(value, durationMs > 0 ? Date.now() + durationMs : null);
|
|
9321
|
+
this._storage.set(key, record);
|
|
9322
|
+
if (durationMs > 0) {
|
|
9323
|
+
record.timeoutId = setTimeout(() => {
|
|
9324
|
+
this._storage.delete(key);
|
|
9325
|
+
}, durationMs);
|
|
9326
|
+
if (typeof record.timeoutId.unref === "function") {
|
|
9327
|
+
record.timeoutId.unref();
|
|
9328
|
+
}
|
|
9329
|
+
}
|
|
9330
|
+
return new LimiterResult(0, durationMs === 0 ? -1 : durationMs, record.value, true);
|
|
9331
|
+
}
|
|
9332
|
+
get(key) {
|
|
9333
|
+
const record = this._storage.get(key);
|
|
9334
|
+
if (!record) return null;
|
|
9335
|
+
const msBeforeExpires = record.expiresAt ? record.expiresAt - Date.now() : -1;
|
|
9336
|
+
return new LimiterResult(0, msBeforeExpires, record.value, false);
|
|
9337
|
+
}
|
|
9338
|
+
delete(key) {
|
|
9339
|
+
const record = this._storage.get(key);
|
|
9340
|
+
if (!record) return false;
|
|
9341
|
+
if (record.timeoutId) {
|
|
9342
|
+
clearTimeout(record.timeoutId);
|
|
9343
|
+
}
|
|
9344
|
+
this._storage.delete(key);
|
|
9345
|
+
return true;
|
|
9346
|
+
}
|
|
9347
|
+
/** Inspect the underlying map. Test-only and not part of the public API. */
|
|
9348
|
+
_dump() {
|
|
9349
|
+
return this._storage.entries();
|
|
9350
|
+
}
|
|
9351
|
+
/** Clear all records. Used by tests and by `Limiter.dispose()`. */
|
|
9352
|
+
clear() {
|
|
9353
|
+
for (const record of this._storage.values()) {
|
|
9354
|
+
if (record.timeoutId) clearTimeout(record.timeoutId);
|
|
9355
|
+
}
|
|
9356
|
+
this._storage.clear();
|
|
9357
|
+
}
|
|
9358
|
+
};
|
|
9359
|
+
|
|
9360
|
+
// src/_third_party/rate-limit/memory.ts
|
|
9361
|
+
var MemoryLimiter = class extends AbstractLimiter {
|
|
9362
|
+
constructor(opts) {
|
|
9363
|
+
super(opts);
|
|
9364
|
+
this._storage = new MemoryStorage();
|
|
9365
|
+
}
|
|
9366
|
+
consume(key, pointsToConsume = 1, options = {}) {
|
|
9367
|
+
return new Promise((resolve2, reject) => {
|
|
9368
|
+
const rlKey = this._getKey(key);
|
|
9369
|
+
const secDuration = this._getKeySecDuration(options);
|
|
9370
|
+
let res = this._storage.incrby(rlKey, pointsToConsume, secDuration);
|
|
9371
|
+
res.remainingPoints = Math.max(this._points - res.consumedPoints, 0);
|
|
9372
|
+
if (res.consumedPoints > this._points) {
|
|
9373
|
+
if (this._blockDuration > 0 && res.consumedPoints <= this._points + pointsToConsume) {
|
|
9374
|
+
res = this._storage.set(rlKey, res.consumedPoints, this._blockDuration);
|
|
9375
|
+
}
|
|
9376
|
+
reject(res);
|
|
9377
|
+
return;
|
|
9378
|
+
}
|
|
9379
|
+
if (this._execEvenly && res.msBeforeNext > 0 && !res.isFirstInDuration) {
|
|
9380
|
+
let delay = Math.ceil(res.msBeforeNext / (res.remainingPoints + 2));
|
|
9381
|
+
if (delay < this._execEvenlyMinDelayMs) {
|
|
9382
|
+
delay = res.consumedPoints * this._execEvenlyMinDelayMs;
|
|
9383
|
+
}
|
|
9384
|
+
res.msBeforeNext = Math.max(res.msBeforeNext - delay, 0);
|
|
9385
|
+
setTimeout(resolve2, delay, res);
|
|
9386
|
+
return;
|
|
9387
|
+
}
|
|
9388
|
+
resolve2(res);
|
|
9389
|
+
});
|
|
9390
|
+
}
|
|
9391
|
+
penalty(key, points = 1, options = {}) {
|
|
9392
|
+
const rlKey = this._getKey(key);
|
|
9393
|
+
const secDuration = this._getKeySecDuration(options);
|
|
9394
|
+
const res = this._storage.incrby(rlKey, points, secDuration);
|
|
9395
|
+
res.remainingPoints = Math.max(this._points - res.consumedPoints, 0);
|
|
9396
|
+
return Promise.resolve(res);
|
|
9397
|
+
}
|
|
9398
|
+
reward(key, points = 1, options = {}) {
|
|
9399
|
+
const rlKey = this._getKey(key);
|
|
9400
|
+
const secDuration = this._getKeySecDuration(options);
|
|
9401
|
+
const res = this._storage.incrby(rlKey, -points, secDuration);
|
|
9402
|
+
res.remainingPoints = Math.max(this._points - res.consumedPoints, 0);
|
|
9403
|
+
return Promise.resolve(res);
|
|
9404
|
+
}
|
|
9405
|
+
block(key, secDuration) {
|
|
9406
|
+
const msDuration = secDuration * 1e3;
|
|
9407
|
+
const initPoints = this._points + 1;
|
|
9408
|
+
this._storage.set(this._getKey(key), initPoints, secDuration);
|
|
9409
|
+
return Promise.resolve(new LimiterResult(0, msDuration === 0 ? -1 : msDuration, initPoints, false));
|
|
9410
|
+
}
|
|
9411
|
+
get(key) {
|
|
9412
|
+
const res = this._storage.get(this._getKey(key));
|
|
9413
|
+
if (res !== null) {
|
|
9414
|
+
res.remainingPoints = Math.max(this._points - res.consumedPoints, 0);
|
|
9415
|
+
}
|
|
9416
|
+
return Promise.resolve(res);
|
|
9417
|
+
}
|
|
9418
|
+
delete(key) {
|
|
9419
|
+
return Promise.resolve(this._storage.delete(this._getKey(key)));
|
|
9420
|
+
}
|
|
9421
|
+
/** Test/teardown helper. Drops every key and clears timers. */
|
|
9422
|
+
dispose() {
|
|
9423
|
+
this._storage.clear();
|
|
9424
|
+
}
|
|
9425
|
+
};
|
|
9426
|
+
|
|
9427
|
+
// src/middleware/brute-force.ts
|
|
9428
|
+
function defaultKeyGenerator(req) {
|
|
9429
|
+
const xff = req.headers["x-forwarded-for"];
|
|
9430
|
+
if (typeof xff === "string" && xff.length > 0) {
|
|
9431
|
+
const first = xff.split(",")[0]?.trim();
|
|
9432
|
+
if (first) return first;
|
|
9433
|
+
}
|
|
9434
|
+
if (typeof req.ip === "string" && req.ip.length > 0) return req.ip;
|
|
9435
|
+
const remote = req.socket?.remoteAddress;
|
|
9436
|
+
return typeof remote === "string" && remote.length > 0 ? remote : "unknown";
|
|
9437
|
+
}
|
|
9438
|
+
function bruteForceProtection(options = {}) {
|
|
9439
|
+
const fastPoints = options.fastPoints ?? 5;
|
|
9440
|
+
const fastDuration = options.fastDuration ?? 60;
|
|
9441
|
+
const slowPoints = options.slowPoints ?? 20;
|
|
9442
|
+
const slowDuration = options.slowDuration ?? 900;
|
|
9443
|
+
const blockDuration = options.blockDuration ?? 900;
|
|
9444
|
+
const keyGenerator = options.keyGenerator ?? defaultKeyGenerator;
|
|
9445
|
+
const statusCode = options.statusCode ?? 429;
|
|
9446
|
+
const message = options.message ?? "Too many login attempts. Please try again later.";
|
|
9447
|
+
const skip = options.skip;
|
|
9448
|
+
const fast = new MemoryLimiter({
|
|
9449
|
+
points: fastPoints,
|
|
9450
|
+
duration: fastDuration,
|
|
9451
|
+
keyPrefix: "arcis:bf:fast"
|
|
9452
|
+
});
|
|
9453
|
+
const slow = new MemoryLimiter({
|
|
9454
|
+
points: slowPoints,
|
|
9455
|
+
duration: slowDuration,
|
|
9456
|
+
blockDuration,
|
|
9457
|
+
keyPrefix: "arcis:bf:slow"
|
|
9458
|
+
});
|
|
9459
|
+
const controller = {
|
|
9460
|
+
reward: (key, points = 1) => slow.reward(key, points),
|
|
9461
|
+
delete: async (key) => {
|
|
9462
|
+
const a = await fast.delete(key);
|
|
9463
|
+
const b = await slow.delete(key);
|
|
9464
|
+
return a || b;
|
|
9465
|
+
},
|
|
9466
|
+
get: (key) => slow.get(key),
|
|
9467
|
+
block: (key, secDuration) => slow.block(key, secDuration)
|
|
9468
|
+
};
|
|
9469
|
+
const handler = async (req, res, next) => {
|
|
9470
|
+
try {
|
|
9471
|
+
if (skip?.(req)) return next();
|
|
9472
|
+
const key = keyGenerator(req);
|
|
9473
|
+
req.arcisBruteForce = controller;
|
|
9474
|
+
const slowRes = await slow.consume(key, 1);
|
|
9475
|
+
const fastRes = await fast.consume(key, 1);
|
|
9476
|
+
res.setHeader("X-RateLimit-Limit", String(slowPoints));
|
|
9477
|
+
res.setHeader(
|
|
9478
|
+
"X-RateLimit-Remaining",
|
|
9479
|
+
String(Math.min(fastRes.remainingPoints, slowRes.remainingPoints))
|
|
9480
|
+
);
|
|
9481
|
+
res.setHeader(
|
|
9482
|
+
"X-RateLimit-Reset",
|
|
9483
|
+
String(Math.ceil(Math.max(slowRes.msBeforeNext, fastRes.msBeforeNext) / 1e3))
|
|
9484
|
+
);
|
|
9485
|
+
next();
|
|
9486
|
+
} catch (rejection) {
|
|
9487
|
+
if (rejection instanceof LimiterResult || isLimiterResultShape(rejection)) {
|
|
9488
|
+
const retryAfter = Math.ceil(rejection.msBeforeNext / 1e3);
|
|
9489
|
+
res.setHeader("X-RateLimit-Limit", String(slowPoints));
|
|
9490
|
+
res.setHeader("X-RateLimit-Remaining", "0");
|
|
9491
|
+
res.setHeader("X-RateLimit-Reset", String(retryAfter));
|
|
9492
|
+
res.setHeader("Retry-After", String(retryAfter));
|
|
9493
|
+
res.status(statusCode).json({ error: message, retryAfter });
|
|
9494
|
+
return;
|
|
9495
|
+
}
|
|
9496
|
+
console.error("[arcis] brute-force middleware error:", rejection);
|
|
9497
|
+
next();
|
|
9498
|
+
}
|
|
9499
|
+
};
|
|
9500
|
+
return Object.assign(handler, { controller });
|
|
9501
|
+
}
|
|
9502
|
+
function isLimiterResultShape(x) {
|
|
9503
|
+
return typeof x === "object" && x !== null && typeof x.consumedPoints === "number" && typeof x.msBeforeNext === "number";
|
|
9504
|
+
}
|
|
9505
|
+
|
|
8809
9506
|
// src/middleware/protect.ts
|
|
8810
9507
|
function getClientIp(req) {
|
|
8811
9508
|
const xff = req?.headers?.["x-forwarded-for"] ?? req?.headers?.["X-Forwarded-For"];
|
|
@@ -8856,6 +9553,10 @@ function protectLogin(options = {}) {
|
|
|
8856
9553
|
const middlewares = [];
|
|
8857
9554
|
const rl = resolve(options.rateLimit, { max: 5, windowMs: 6e4 });
|
|
8858
9555
|
if (rl) middlewares.push(createRateLimiter(rl));
|
|
9556
|
+
if (options.bruteForce) {
|
|
9557
|
+
const bfOpts = options.bruteForce === true ? {} : options.bruteForce;
|
|
9558
|
+
middlewares.push(bruteForceProtection(bfOpts));
|
|
9559
|
+
}
|
|
8859
9560
|
const bot = resolve(options.bot, {
|
|
8860
9561
|
deny: ["AUTOMATED"],
|
|
8861
9562
|
statusCode: 403,
|