@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.
Files changed (42) hide show
  1. package/README.md +1 -1
  2. package/dist/core/constants.d.ts +2 -2
  3. package/dist/core/constants.d.ts.map +1 -1
  4. package/dist/core/index.js +11 -3
  5. package/dist/core/index.js.map +1 -1
  6. package/dist/core/index.mjs +11 -3
  7. package/dist/core/index.mjs.map +1 -1
  8. package/dist/index.js +125 -46
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +126 -47
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/logging/index.js.map +1 -1
  13. package/dist/logging/index.mjs.map +1 -1
  14. package/dist/middleware/csrf.d.ts.map +1 -1
  15. package/dist/middleware/index.js +62 -30
  16. package/dist/middleware/index.js.map +1 -1
  17. package/dist/middleware/index.mjs +63 -31
  18. package/dist/middleware/index.mjs.map +1 -1
  19. package/dist/middleware/rate-limit.d.ts.map +1 -1
  20. package/dist/sanitizers/encode.d.ts.map +1 -1
  21. package/dist/sanitizers/index.d.ts +1 -0
  22. package/dist/sanitizers/index.d.ts.map +1 -1
  23. package/dist/sanitizers/index.js +90 -32
  24. package/dist/sanitizers/index.js.map +1 -1
  25. package/dist/sanitizers/index.mjs +88 -33
  26. package/dist/sanitizers/index.mjs.map +1 -1
  27. package/dist/sanitizers/ldap.d.ts +42 -0
  28. package/dist/sanitizers/ldap.d.ts.map +1 -0
  29. package/dist/sanitizers/path.d.ts.map +1 -1
  30. package/dist/sanitizers/sanitize.d.ts.map +1 -1
  31. package/dist/sanitizers/ssti.d.ts.map +1 -1
  32. package/dist/stores/index.js +21 -1
  33. package/dist/stores/index.js.map +1 -1
  34. package/dist/stores/index.mjs +21 -1
  35. package/dist/stores/index.mjs.map +1 -1
  36. package/dist/stores/memory.d.ts +4 -10
  37. package/dist/stores/memory.d.ts.map +1 -1
  38. package/dist/validation/index.js +38 -21
  39. package/dist/validation/index.js.map +1 -1
  40. package/dist/validation/index.mjs +38 -21
  41. package/dist/validation/index.mjs.map +1 -1
  42. package/package.json +2 -2
@@ -29,7 +29,15 @@ var XSS_REMOVE_PATTERNS = [
29
29
  /javascript\s*:/gi,
30
30
  /vbscript\s*:/gi,
31
31
  /** data: URIs with HTML/script content */
32
- /data\s*:\s*text\/html[^>\s]*/gi
32
+ /data\s*:\s*text\/html[^>\s]*/gi,
33
+ /** form tag injection — phishing via action= redirection */
34
+ /<form[\s>][^>]*/gi,
35
+ /** meta tag injection — http-equiv refresh or CSP bypass */
36
+ /<meta[\s>][^>]*/gi,
37
+ /** base href hijacking */
38
+ /<base[\s>][^>]*/gi,
39
+ /** link tag injection — stylesheet or preload attacks */
40
+ /<link[\s>][^>]*/gi
33
41
  ];
34
42
  var SQL_PATTERNS = [
35
43
  /** SQL keywords */
@@ -93,8 +101,8 @@ var COMMAND_PATTERNS = [
93
101
  /[;&|`]/g,
94
102
  /** Command substitution: $( ... ) — matched as a pair to reduce false positives */
95
103
  /\$\(/g,
96
- /** URL-encoded newline/carriage-return injection (%0a, %0d) */
97
- /%0[ad]/gi
104
+ /** URL-encoded control characters (%00-%0F): null, tab, vtab, formfeed, LF, CR */
105
+ /%0[0-9a-f]/gi
98
106
  ];
99
107
  var VALIDATION = {
100
108
  /**
@@ -259,26 +267,31 @@ function sanitizePath(input, collectThreats = false) {
259
267
  const threats = [];
260
268
  let value = input;
261
269
  let wasSanitized = false;
262
- for (const pattern of PATH_PATTERNS) {
263
- pattern.lastIndex = 0;
264
- if (pattern.test(value)) {
270
+ value = value.normalize("NFKC");
271
+ let prev;
272
+ do {
273
+ prev = value;
274
+ for (const pattern of PATH_PATTERNS) {
265
275
  pattern.lastIndex = 0;
266
- if (collectThreats) {
267
- const matches = value.match(pattern);
268
- if (matches) {
269
- for (const match of matches) {
270
- threats.push({
271
- type: "path_traversal",
272
- pattern: pattern.source,
273
- original: match
274
- });
276
+ if (pattern.test(value)) {
277
+ pattern.lastIndex = 0;
278
+ if (collectThreats) {
279
+ const matches = value.match(pattern);
280
+ if (matches) {
281
+ for (const match of matches) {
282
+ threats.push({
283
+ type: "path_traversal",
284
+ pattern: pattern.source,
285
+ original: match
286
+ });
287
+ }
275
288
  }
276
289
  }
290
+ value = value.replace(pattern, "");
291
+ wasSanitized = true;
277
292
  }
278
- value = value.replace(pattern, "");
279
- wasSanitized = true;
280
293
  }
281
- }
294
+ } while (value !== prev);
282
295
  if (collectThreats) {
283
296
  return { value, wasSanitized, threats };
284
297
  }
@@ -336,7 +349,7 @@ function sanitizeString(value, options = {}) {
336
349
  if (value.length > maxSize) {
337
350
  throw new InputTooLargeError(maxSize, value.length);
338
351
  }
339
- const reject = options.mode !== "sanitize";
352
+ const reject = options.mode === "reject";
340
353
  let result = value;
341
354
  if (options.sql !== false) {
342
355
  if (reject) {
@@ -791,8 +804,12 @@ function checkPrivateIp(hostname) {
791
804
  if (hostname === "metadata.google.internal" || hostname === "metadata.internal" || hostname === "metadata.azure.internal") {
792
805
  return "cloud metadata endpoint";
793
806
  }
794
- const ipv6 = hostname.replace(/^\[|\]$/g, "");
795
- if (ipv6 === "::1" || ipv6 === "::" || ipv6.startsWith("fc") || ipv6.startsWith("fd") || ipv6.startsWith("fe80")) {
807
+ let ipv6 = hostname.replace(/^\[|\]$/g, "");
808
+ const zoneIdx = ipv6.indexOf("%");
809
+ if (zoneIdx !== -1) {
810
+ ipv6 = ipv6.slice(0, zoneIdx);
811
+ }
812
+ if (ipv6 === "::1" || ipv6 === "::" || /^fc[0-9a-f]{2}:/i.test(ipv6) || /^fd[0-9a-f]{2}:/i.test(ipv6) || /^fe80:/i.test(ipv6) || /^ff[0-9a-f]{2}:/i.test(ipv6)) {
796
813
  return "private IPv6 address";
797
814
  }
798
815
  const mappedDotted = ipv6.match(/^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i);