@arcis/node 1.4.0 → 1.4.2
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 +1 -1
- package/dist/core/constants.d.ts +2 -2
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/index.js +11 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +11 -3
- package/dist/core/index.mjs.map +1 -1
- package/dist/index.js +125 -46
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +126 -47
- package/dist/index.mjs.map +1 -1
- package/dist/logging/index.js.map +1 -1
- package/dist/logging/index.mjs.map +1 -1
- package/dist/middleware/csrf.d.ts.map +1 -1
- package/dist/middleware/index.js +62 -30
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +63 -31
- package/dist/middleware/index.mjs.map +1 -1
- package/dist/middleware/rate-limit.d.ts.map +1 -1
- package/dist/sanitizers/encode.d.ts.map +1 -1
- package/dist/sanitizers/index.d.ts +1 -0
- package/dist/sanitizers/index.d.ts.map +1 -1
- package/dist/sanitizers/index.js +90 -32
- package/dist/sanitizers/index.js.map +1 -1
- package/dist/sanitizers/index.mjs +88 -33
- package/dist/sanitizers/index.mjs.map +1 -1
- package/dist/sanitizers/ldap.d.ts +42 -0
- package/dist/sanitizers/ldap.d.ts.map +1 -0
- package/dist/sanitizers/path.d.ts.map +1 -1
- package/dist/sanitizers/sanitize.d.ts.map +1 -1
- package/dist/sanitizers/ssti.d.ts.map +1 -1
- package/dist/stores/index.js +21 -1
- package/dist/stores/index.js.map +1 -1
- package/dist/stores/index.mjs +21 -1
- package/dist/stores/index.mjs.map +1 -1
- package/dist/stores/memory.d.ts +4 -10
- package/dist/stores/memory.d.ts.map +1 -1
- package/dist/validation/index.js +38 -21
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/index.mjs +38 -21
- package/dist/validation/index.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -25,7 +25,15 @@ var XSS_PATTERNS = [
|
|
|
25
25
|
/** URL-encoded script tags */
|
|
26
26
|
/%3Cscript/gi,
|
|
27
27
|
/** SVG with onload */
|
|
28
|
-
/<svg[^>]*onload/gi
|
|
28
|
+
/<svg[^>]*onload/gi,
|
|
29
|
+
/** form tags — phishing/credential harvesting via action= redirection */
|
|
30
|
+
/<form[\s>]/gi,
|
|
31
|
+
/** meta tags — http-equiv refresh redirects or CSP bypass */
|
|
32
|
+
/<meta[\s>]/gi,
|
|
33
|
+
/** base href hijacking — redirects all relative URLs to attacker domain */
|
|
34
|
+
/<base[\s>]/gi,
|
|
35
|
+
/** link tag injection — stylesheet or preload CSRF attacks */
|
|
36
|
+
/<link[\s>]/gi
|
|
29
37
|
];
|
|
30
38
|
var XSS_REMOVE_PATTERNS = [
|
|
31
39
|
/** Full script blocks (content + tags) */
|
|
@@ -52,7 +60,15 @@ var XSS_REMOVE_PATTERNS = [
|
|
|
52
60
|
/javascript\s*:/gi,
|
|
53
61
|
/vbscript\s*:/gi,
|
|
54
62
|
/** data: URIs with HTML/script content */
|
|
55
|
-
/data\s*:\s*text\/html[^>\s]*/gi
|
|
63
|
+
/data\s*:\s*text\/html[^>\s]*/gi,
|
|
64
|
+
/** form tag injection — phishing via action= redirection */
|
|
65
|
+
/<form[\s>][^>]*/gi,
|
|
66
|
+
/** meta tag injection — http-equiv refresh or CSP bypass */
|
|
67
|
+
/<meta[\s>][^>]*/gi,
|
|
68
|
+
/** base href hijacking */
|
|
69
|
+
/<base[\s>][^>]*/gi,
|
|
70
|
+
/** link tag injection — stylesheet or preload attacks */
|
|
71
|
+
/<link[\s>][^>]*/gi
|
|
56
72
|
];
|
|
57
73
|
var SQL_PATTERNS = [
|
|
58
74
|
/** SQL keywords */
|
|
@@ -116,8 +132,8 @@ var COMMAND_PATTERNS = [
|
|
|
116
132
|
/[;&|`]/g,
|
|
117
133
|
/** Command substitution: $( ... ) — matched as a pair to reduce false positives */
|
|
118
134
|
/\$\(/g,
|
|
119
|
-
/** URL-encoded
|
|
120
|
-
/%0[
|
|
135
|
+
/** URL-encoded control characters (%00-%0F): null, tab, vtab, formfeed, LF, CR */
|
|
136
|
+
/%0[0-9a-f]/gi
|
|
121
137
|
];
|
|
122
138
|
var DANGEROUS_PROTO_KEYS = /* @__PURE__ */ new Set([
|
|
123
139
|
"__proto__",
|
|
@@ -321,26 +337,31 @@ function sanitizePath(input, collectThreats = false) {
|
|
|
321
337
|
const threats = [];
|
|
322
338
|
let value = input;
|
|
323
339
|
let wasSanitized = false;
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
340
|
+
value = value.normalize("NFKC");
|
|
341
|
+
let prev;
|
|
342
|
+
do {
|
|
343
|
+
prev = value;
|
|
344
|
+
for (const pattern of PATH_PATTERNS) {
|
|
327
345
|
pattern.lastIndex = 0;
|
|
328
|
-
if (
|
|
329
|
-
|
|
330
|
-
if (
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
346
|
+
if (pattern.test(value)) {
|
|
347
|
+
pattern.lastIndex = 0;
|
|
348
|
+
if (collectThreats) {
|
|
349
|
+
const matches = value.match(pattern);
|
|
350
|
+
if (matches) {
|
|
351
|
+
for (const match of matches) {
|
|
352
|
+
threats.push({
|
|
353
|
+
type: "path_traversal",
|
|
354
|
+
pattern: pattern.source,
|
|
355
|
+
original: match
|
|
356
|
+
});
|
|
357
|
+
}
|
|
337
358
|
}
|
|
338
359
|
}
|
|
360
|
+
value = value.replace(pattern, "");
|
|
361
|
+
wasSanitized = true;
|
|
339
362
|
}
|
|
340
|
-
value = value.replace(pattern, "");
|
|
341
|
-
wasSanitized = true;
|
|
342
363
|
}
|
|
343
|
-
}
|
|
364
|
+
} while (value !== prev);
|
|
344
365
|
if (collectThreats) {
|
|
345
366
|
return { value, wasSanitized, threats };
|
|
346
367
|
}
|
|
@@ -348,9 +369,10 @@ function sanitizePath(input, collectThreats = false) {
|
|
|
348
369
|
}
|
|
349
370
|
function detectPathTraversal(input) {
|
|
350
371
|
if (typeof input !== "string") return false;
|
|
372
|
+
const normalized = input.normalize("NFKC");
|
|
351
373
|
for (const pattern of PATH_PATTERNS) {
|
|
352
374
|
pattern.lastIndex = 0;
|
|
353
|
-
if (pattern.test(
|
|
375
|
+
if (pattern.test(normalized)) {
|
|
354
376
|
return true;
|
|
355
377
|
}
|
|
356
378
|
}
|
|
@@ -408,7 +430,7 @@ function sanitizeString(value, options = {}) {
|
|
|
408
430
|
if (value.length > maxSize) {
|
|
409
431
|
throw new InputTooLargeError(maxSize, value.length);
|
|
410
432
|
}
|
|
411
|
-
const reject = options.mode
|
|
433
|
+
const reject = options.mode === "reject";
|
|
412
434
|
let result = value;
|
|
413
435
|
if (options.sql !== false) {
|
|
414
436
|
if (reject) {
|
|
@@ -563,10 +585,22 @@ var SSTI_DETECT_PATTERNS = [
|
|
|
563
585
|
/\{\{\s*(?:self|request|lipsum|cycler|joiner|namespace|range)\b/gi
|
|
564
586
|
];
|
|
565
587
|
var SSTI_REMOVE_PATTERNS = [
|
|
588
|
+
/** Jinja2 / Twig: {{ ... }} — always strip (not valid in any JS context) */
|
|
566
589
|
/\{\{.*?\}\}/g,
|
|
567
|
-
|
|
590
|
+
/**
|
|
591
|
+
* Freemarker / Spring EL: ${...} — only strip when the expression contains
|
|
592
|
+
* operators (?!*+-/), method calls (), or known-dangerous prefixes.
|
|
593
|
+
* Bare ${name} and ${user.name} are left intact (JS template literal syntax).
|
|
594
|
+
*/
|
|
595
|
+
/\$\{[^}]*[?!()*+\-/][^}]*\}/g,
|
|
596
|
+
/** ERB / EJS: <%= ... %> */
|
|
568
597
|
/<%[=\-]?.*?%>/gs,
|
|
569
|
-
|
|
598
|
+
/**
|
|
599
|
+
* Pug / Jade: #{...} — same narrowing as ${ above.
|
|
600
|
+
* #{name} output expressions are left intact.
|
|
601
|
+
*/
|
|
602
|
+
/#\{[^}]*[?!()*+\-/][^}]*\}/g,
|
|
603
|
+
/** Python dunder sandbox escape — always strip */
|
|
570
604
|
/__(?:class|mro|subclasses|globals|builtins|import)__/gi
|
|
571
605
|
];
|
|
572
606
|
function sanitizeSsti(input, collectThreats = false) {
|
|
@@ -930,16 +964,18 @@ function encodeForAttribute(value) {
|
|
|
930
964
|
function encodeForJs(value) {
|
|
931
965
|
if (!value) return "";
|
|
932
966
|
let result = "";
|
|
933
|
-
for (
|
|
934
|
-
const
|
|
935
|
-
if (
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
result +=
|
|
939
|
-
} else if (
|
|
940
|
-
result += `\\x${
|
|
967
|
+
for (const char of value) {
|
|
968
|
+
const cp = char.codePointAt(0);
|
|
969
|
+
if (cp >= 48 && cp <= 57 || // 0-9
|
|
970
|
+
cp >= 65 && cp <= 90 || // A-Z
|
|
971
|
+
cp >= 97 && cp <= 122) {
|
|
972
|
+
result += char;
|
|
973
|
+
} else if (cp < 256) {
|
|
974
|
+
result += `\\x${cp.toString(16).toUpperCase().padStart(2, "0")}`;
|
|
975
|
+
} else if (cp <= 65535) {
|
|
976
|
+
result += `\\u${cp.toString(16).toUpperCase().padStart(4, "0")}`;
|
|
941
977
|
} else {
|
|
942
|
-
result += `\\u${
|
|
978
|
+
result += `\\u{${cp.toString(16).toUpperCase()}}`;
|
|
943
979
|
}
|
|
944
980
|
}
|
|
945
981
|
return result;
|
|
@@ -966,6 +1002,25 @@ function encodeForCss(value) {
|
|
|
966
1002
|
return result;
|
|
967
1003
|
}
|
|
968
1004
|
|
|
969
|
-
|
|
1005
|
+
// src/sanitizers/ldap.ts
|
|
1006
|
+
var LDAP_FILTER_CHARS = /[*()\\\x00]/g;
|
|
1007
|
+
var LDAP_DN_CHARS = /[,+<>;"=\/\\\x00*()\x00]/g;
|
|
1008
|
+
var LDAP_DETECT_PATTERN = /[*()\\\x00]/;
|
|
1009
|
+
var LDAP_INJECTION_PATTERN = /\)\s*\(|\*\s*\)\s*\(/;
|
|
1010
|
+
var escapeChar = (char) => "\\" + char.charCodeAt(0).toString(16).padStart(2, "0");
|
|
1011
|
+
function sanitizeLdapFilter(input) {
|
|
1012
|
+
if (typeof input !== "string") return String(input);
|
|
1013
|
+
return input.replace(LDAP_FILTER_CHARS, escapeChar);
|
|
1014
|
+
}
|
|
1015
|
+
function sanitizeLdapDn(input) {
|
|
1016
|
+
if (typeof input !== "string") return String(input);
|
|
1017
|
+
return input.replace(LDAP_DN_CHARS, escapeChar);
|
|
1018
|
+
}
|
|
1019
|
+
function detectLdapInjection(input) {
|
|
1020
|
+
if (typeof input !== "string") return false;
|
|
1021
|
+
return LDAP_DETECT_PATTERN.test(input) || LDAP_INJECTION_PATTERN.test(input);
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
export { createSanitizer, detectCommandInjection, detectHeaderInjection, detectJsonpInjection, detectLdapInjection, detectNoSqlInjection, detectPathTraversal, detectPii, detectPrototypePollution, detectSql, detectSsti, detectXss, detectXxe, encodeForAttribute, encodeForCss, encodeForHtml, encodeForJs, encodeForUrl, encodeHtmlEntities, getDangerousOperators, getDangerousProtoKeys, isDangerousNoSqlKey, isDangerousProtoKey, isPlainObject, redactObjectPii, redactPii, sanitizeCommand, sanitizeHeaderValue, sanitizeHeaders, sanitizeJsonpCallback, sanitizeLdapDn, sanitizeLdapFilter, sanitizeObject, sanitizePath, sanitizeSql, sanitizeSsti, sanitizeString, sanitizeXss, sanitizeXxe, scanObjectPii, scanPii };
|
|
970
1025
|
//# sourceMappingURL=index.mjs.map
|
|
971
1026
|
//# sourceMappingURL=index.mjs.map
|