@arcis/node 1.1.0 → 1.2.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.
Files changed (50) hide show
  1. package/README.md +156 -211
  2. package/dist/core/index.d.mts +4 -4
  3. package/dist/core/index.d.ts +4 -4
  4. package/dist/core/index.js +13 -2
  5. package/dist/core/index.js.map +1 -1
  6. package/dist/core/index.mjs +13 -2
  7. package/dist/core/index.mjs.map +1 -1
  8. package/dist/{index-CslcoZUN.d.mts → index-A-m-pPeW.d.mts} +1 -1
  9. package/dist/{index-CCcPuTBo.d.mts → index-CgK94hY_.d.mts} +96 -2
  10. package/dist/{index-iCOw8Fcg.d.ts → index-Co5kPRZz.d.ts} +1 -1
  11. package/dist/{index-BvcFpoR3.d.ts → index-D_bdJcF0.d.ts} +96 -2
  12. package/dist/index.d.mts +4 -4
  13. package/dist/index.d.ts +4 -4
  14. package/dist/index.js +553 -5
  15. package/dist/index.js.map +1 -1
  16. package/dist/index.mjs +540 -7
  17. package/dist/index.mjs.map +1 -1
  18. package/dist/logging/index.d.mts +1 -1
  19. package/dist/logging/index.d.ts +1 -1
  20. package/dist/logging/index.js +12 -1
  21. package/dist/logging/index.js.map +1 -1
  22. package/dist/logging/index.mjs +12 -1
  23. package/dist/logging/index.mjs.map +1 -1
  24. package/dist/middleware/index.d.mts +2 -2
  25. package/dist/middleware/index.d.ts +2 -2
  26. package/dist/middleware/index.js +146 -4
  27. package/dist/middleware/index.js.map +1 -1
  28. package/dist/middleware/index.mjs +143 -5
  29. package/dist/middleware/index.mjs.map +1 -1
  30. package/dist/{headers-DBQedhrb.d.mts → pii-CXcHMlnX.d.mts} +156 -2
  31. package/dist/{headers-BJq2OA0i.d.ts → pii-DhNpl7M3.d.ts} +156 -2
  32. package/dist/sanitizers/index.d.mts +2 -2
  33. package/dist/sanitizers/index.d.ts +2 -2
  34. package/dist/sanitizers/index.js +331 -3
  35. package/dist/sanitizers/index.js.map +1 -1
  36. package/dist/sanitizers/index.mjs +321 -4
  37. package/dist/sanitizers/index.mjs.map +1 -1
  38. package/dist/stores/index.d.mts +1 -1
  39. package/dist/stores/index.d.ts +1 -1
  40. package/dist/stores/index.js.map +1 -1
  41. package/dist/stores/index.mjs.map +1 -1
  42. package/dist/{types-BOdL3ZWo.d.mts → types-CsOFHoD9.d.mts} +6 -1
  43. package/dist/{types-BOdL3ZWo.d.ts → types-CsOFHoD9.d.ts} +6 -1
  44. package/dist/validation/index.d.mts +2 -2
  45. package/dist/validation/index.d.ts +2 -2
  46. package/dist/validation/index.js +105 -3
  47. package/dist/validation/index.js.map +1 -1
  48. package/dist/validation/index.mjs +105 -3
  49. package/dist/validation/index.mjs.map +1 -1
  50. package/package.json +114 -114
@@ -51,7 +51,11 @@ var SQL_PATTERNS = [
51
51
  /** Time-based blind: SLEEP() */
52
52
  /\bSLEEP\s*\(\s*\d+\s*\)/gi,
53
53
  /** Time-based blind: BENCHMARK() */
54
- /\bBENCHMARK\s*\(/gi
54
+ /\bBENCHMARK\s*\(/gi,
55
+ /** Time-based blind: PostgreSQL pg_sleep() */
56
+ /\bpg_sleep\s*\(/gi,
57
+ /** Time-based blind: MSSQL WAITFOR DELAY */
58
+ /\bWAITFOR\s+DELAY\b/gi
55
59
  ];
56
60
  var PATH_PATTERNS = [
57
61
  /** Unix path traversal */
@@ -69,6 +73,10 @@ var PATH_PATTERNS = [
69
73
  /\.%2e[\\/]/gi,
70
74
  /** Fully URL-encoded: %2e%2e%2f */
71
75
  /%2e%2e%2f/gi,
76
+ /** Double URL-encoded forward slash: %252f */
77
+ /%252f/gi,
78
+ /** Dotdotslash bypass: ....// or ....\\ */
79
+ /\.{2,}[/\\]{2,}/g,
72
80
  /** Null byte injection in paths */
73
81
  /\0/g
74
82
  ];
@@ -84,7 +92,9 @@ var COMMAND_PATTERNS = [
84
92
  */
85
93
  /[;&|`]/g,
86
94
  /** Command substitution: $( ... ) — matched as a pair to reduce false positives */
87
- /\$\(/g
95
+ /\$\(/g,
96
+ /** URL-encoded newline/carriage-return injection (%0a, %0d) */
97
+ /%0[ad]/gi
88
98
  ];
89
99
  var VALIDATION = {
90
100
  /**
@@ -735,6 +745,18 @@ function validateUrl(url, options = {}) {
735
745
  return { safe: false, reason: "loopback address" };
736
746
  }
737
747
  }
748
+ if (!allowLocalhost || !allowPrivate) {
749
+ const decimalCheck = checkDecimalIp(hostname, allowLocalhost, allowPrivate);
750
+ if (decimalCheck) {
751
+ return { safe: false, reason: decimalCheck };
752
+ }
753
+ }
754
+ if (!allowLocalhost || !allowPrivate) {
755
+ const octalCheck = checkOctalIp(hostname, allowLocalhost, allowPrivate);
756
+ if (octalCheck) {
757
+ return { safe: false, reason: octalCheck };
758
+ }
759
+ }
738
760
  if (!allowPrivate) {
739
761
  const privateCheck = checkPrivateIp(hostname);
740
762
  if (privateCheck) {
@@ -766,13 +788,93 @@ function checkPrivateIp(hostname) {
766
788
  if (/^0\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(hostname)) {
767
789
  return "current network address (0.0.0.0/8)";
768
790
  }
769
- if (hostname === "metadata.google.internal" || hostname === "metadata.internal") {
791
+ if (hostname === "metadata.google.internal" || hostname === "metadata.internal" || hostname === "metadata.azure.internal") {
770
792
  return "cloud metadata endpoint";
771
793
  }
772
794
  const ipv6 = hostname.replace(/^\[|\]$/g, "");
773
795
  if (ipv6 === "::1" || ipv6 === "::" || ipv6.startsWith("fc") || ipv6.startsWith("fd") || ipv6.startsWith("fe80")) {
774
796
  return "private IPv6 address";
775
797
  }
798
+ const mappedDotted = ipv6.match(/^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i);
799
+ if (mappedDotted) {
800
+ const mappedIp = mappedDotted[1];
801
+ if (/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(mappedIp)) {
802
+ return "IPv6-mapped loopback address";
803
+ }
804
+ const mappedCheck = checkPrivateIp(mappedIp);
805
+ if (mappedCheck) {
806
+ return `IPv6-mapped ${mappedCheck}`;
807
+ }
808
+ }
809
+ const mappedHex = ipv6.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i);
810
+ if (mappedHex) {
811
+ const hi = parseInt(mappedHex[1], 16);
812
+ const lo = parseInt(mappedHex[2], 16);
813
+ const a = hi >> 8 & 255;
814
+ const b = hi & 255;
815
+ const c = lo >> 8 & 255;
816
+ const d = lo & 255;
817
+ const dotted = `${a}.${b}.${c}.${d}`;
818
+ if (a === 127) {
819
+ return "IPv6-mapped loopback address";
820
+ }
821
+ const hexCheck = checkPrivateIp(dotted);
822
+ if (hexCheck) {
823
+ return `IPv6-mapped ${hexCheck}`;
824
+ }
825
+ }
826
+ return null;
827
+ }
828
+ function checkDecimalIp(hostname, allowLocalhost, allowPrivate) {
829
+ if (!/^\d+$/.test(hostname)) return null;
830
+ const num = parseInt(hostname, 10);
831
+ if (isNaN(num) || num < 0 || num > 4294967295) return null;
832
+ const a = num >>> 24 & 255;
833
+ const b = num >>> 16 & 255;
834
+ const c = num >>> 8 & 255;
835
+ const d = num & 255;
836
+ const dotted = `${a}.${b}.${c}.${d}`;
837
+ if (!allowLocalhost && a === 127) {
838
+ return `loopback address (decimal IP: ${dotted})`;
839
+ }
840
+ if (!allowPrivate) {
841
+ const privateCheck = checkPrivateIp(dotted);
842
+ if (privateCheck) {
843
+ return `${privateCheck} (decimal IP: ${dotted})`;
844
+ }
845
+ }
846
+ return null;
847
+ }
848
+ function checkOctalIp(hostname, allowLocalhost, allowPrivate) {
849
+ const parts = hostname.split(".");
850
+ if (parts.length !== 4) return null;
851
+ const hasAlternateNotation = parts.some((p) => /^0[0-7]+$/.test(p) || /^0x[0-9a-fA-F]+$/i.test(p));
852
+ if (!hasAlternateNotation) return null;
853
+ const octets = [];
854
+ for (const part of parts) {
855
+ let val;
856
+ if (/^0x[0-9a-fA-F]+$/i.test(part)) {
857
+ val = parseInt(part, 16);
858
+ } else if (/^0[0-7]*$/.test(part)) {
859
+ val = parseInt(part, 8);
860
+ } else if (/^\d+$/.test(part)) {
861
+ val = parseInt(part, 10);
862
+ } else {
863
+ return null;
864
+ }
865
+ if (val < 0 || val > 255) return null;
866
+ octets.push(val);
867
+ }
868
+ const dotted = octets.join(".");
869
+ if (!allowLocalhost && octets[0] === 127) {
870
+ return `loopback address (octal IP: ${dotted})`;
871
+ }
872
+ if (!allowPrivate) {
873
+ const privateCheck = checkPrivateIp(dotted);
874
+ if (privateCheck) {
875
+ return `${privateCheck} (octal IP: ${dotted})`;
876
+ }
877
+ }
776
878
  return null;
777
879
  }
778
880