@arcis/node 1.1.0 → 1.3.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/README.md +156 -211
- package/dist/core/index.d.mts +4 -4
- package/dist/core/index.d.ts +4 -4
- package/dist/core/index.js +13 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +13 -2
- package/dist/core/index.mjs.map +1 -1
- package/dist/{headers-DBQedhrb.d.mts → encode-CrQCGlBq.d.mts} +202 -2
- package/dist/{headers-BJq2OA0i.d.ts → encode-jl9sOwmA.d.ts} +202 -2
- package/dist/{index-BvcFpoR3.d.ts → index-BAhgn9V2.d.ts} +96 -2
- package/dist/{index-iCOw8Fcg.d.ts → index-BGNKspqH.d.ts} +1 -1
- package/dist/{index-CslcoZUN.d.mts → index-Cd02z-0j.d.mts} +1 -1
- package/dist/{index-CCcPuTBo.d.mts → index-DgJtWMSj.d.mts} +96 -2
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +647 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +629 -9
- package/dist/index.mjs.map +1 -1
- package/dist/logging/index.d.mts +1 -1
- package/dist/logging/index.d.ts +1 -1
- package/dist/logging/index.js +12 -1
- package/dist/logging/index.js.map +1 -1
- package/dist/logging/index.mjs +12 -1
- package/dist/logging/index.mjs.map +1 -1
- package/dist/middleware/index.d.mts +2 -2
- package/dist/middleware/index.d.ts +2 -2
- package/dist/middleware/index.js +168 -6
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +165 -7
- package/dist/middleware/index.mjs.map +1 -1
- package/dist/sanitizers/index.d.mts +2 -2
- package/dist/sanitizers/index.d.ts +2 -2
- package/dist/sanitizers/index.js +403 -3
- package/dist/sanitizers/index.js.map +1 -1
- package/dist/sanitizers/index.mjs +388 -4
- package/dist/sanitizers/index.mjs.map +1 -1
- package/dist/stores/index.d.mts +1 -1
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.js.map +1 -1
- package/dist/stores/index.mjs.map +1 -1
- package/dist/{types-BOdL3ZWo.d.mts → types-BOkx5YJc.d.mts} +17 -2
- package/dist/{types-BOdL3ZWo.d.ts → types-BOkx5YJc.d.ts} +17 -2
- package/dist/validation/index.d.mts +2 -2
- package/dist/validation/index.d.ts +2 -2
- package/dist/validation/index.js +105 -3
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/index.mjs +105 -3
- package/dist/validation/index.mjs.map +1 -1
- 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
|
|