@arcis/node 1.4.4 → 1.5.1

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 (144) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -6
  3. package/dist/astro/index.js +6141 -0
  4. package/dist/astro/index.js.map +1 -0
  5. package/dist/astro/index.mjs +6136 -0
  6. package/dist/astro/index.mjs.map +1 -0
  7. package/dist/bun/index.js +6195 -0
  8. package/dist/bun/index.js.map +1 -0
  9. package/dist/bun/index.mjs +6189 -0
  10. package/dist/bun/index.mjs.map +1 -0
  11. package/dist/core/constants.d.ts +3 -2
  12. package/dist/core/constants.d.ts.map +1 -1
  13. package/dist/core/index.js +4 -3
  14. package/dist/core/index.js.map +1 -1
  15. package/dist/core/index.mjs +4 -3
  16. package/dist/core/index.mjs.map +1 -1
  17. package/dist/core/types.d.ts +32 -0
  18. package/dist/core/types.d.ts.map +1 -1
  19. package/dist/fastify/index.js +6160 -0
  20. package/dist/fastify/index.js.map +1 -0
  21. package/dist/fastify/index.mjs +6155 -0
  22. package/dist/fastify/index.mjs.map +1 -0
  23. package/dist/guards.d.ts +156 -0
  24. package/dist/guards.d.ts.map +1 -0
  25. package/dist/hono/index.js +6159 -0
  26. package/dist/hono/index.js.map +1 -0
  27. package/dist/hono/index.mjs +6154 -0
  28. package/dist/hono/index.mjs.map +1 -0
  29. package/dist/index.d.ts +23 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +7126 -178
  32. package/dist/index.js.map +1 -1
  33. package/dist/index.mjs +7088 -179
  34. package/dist/index.mjs.map +1 -1
  35. package/dist/koa/index.js +6158 -0
  36. package/dist/koa/index.js.map +1 -0
  37. package/dist/koa/index.mjs +6153 -0
  38. package/dist/koa/index.mjs.map +1 -0
  39. package/dist/logging/index.js.map +1 -1
  40. package/dist/logging/index.mjs.map +1 -1
  41. package/dist/logging/redactor.d.ts.map +1 -1
  42. package/dist/middleware/astro.d.ts +64 -0
  43. package/dist/middleware/astro.d.ts.map +1 -0
  44. package/dist/middleware/bot-detection.d.ts.map +1 -1
  45. package/dist/middleware/bun.d.ts +75 -0
  46. package/dist/middleware/bun.d.ts.map +1 -0
  47. package/dist/middleware/csrf.d.ts.map +1 -1
  48. package/dist/middleware/error-handler.d.ts.map +1 -1
  49. package/dist/middleware/fastify.d.ts +89 -0
  50. package/dist/middleware/fastify.d.ts.map +1 -0
  51. package/dist/middleware/graphql.d.ts +35 -0
  52. package/dist/middleware/graphql.d.ts.map +1 -0
  53. package/dist/middleware/hono.d.ts +63 -0
  54. package/dist/middleware/hono.d.ts.map +1 -0
  55. package/dist/middleware/index.d.ts +12 -0
  56. package/dist/middleware/index.d.ts.map +1 -1
  57. package/dist/middleware/index.js +6469 -119
  58. package/dist/middleware/index.js.map +1 -1
  59. package/dist/middleware/index.mjs +6459 -120
  60. package/dist/middleware/index.mjs.map +1 -1
  61. package/dist/middleware/koa.d.ts +84 -0
  62. package/dist/middleware/koa.d.ts.map +1 -0
  63. package/dist/middleware/main.d.ts +0 -30
  64. package/dist/middleware/main.d.ts.map +1 -1
  65. package/dist/middleware/mass-assign.d.ts +81 -0
  66. package/dist/middleware/mass-assign.d.ts.map +1 -0
  67. package/dist/middleware/method-allowlist.d.ts +66 -0
  68. package/dist/middleware/method-allowlist.d.ts.map +1 -0
  69. package/dist/middleware/nestjs.d.ts +62 -0
  70. package/dist/middleware/nestjs.d.ts.map +1 -0
  71. package/dist/middleware/nextjs.d.ts +102 -0
  72. package/dist/middleware/nextjs.d.ts.map +1 -0
  73. package/dist/middleware/nuxt.d.ts +61 -0
  74. package/dist/middleware/nuxt.d.ts.map +1 -0
  75. package/dist/middleware/overload.d.ts +92 -0
  76. package/dist/middleware/overload.d.ts.map +1 -0
  77. package/dist/middleware/protect.d.ts +91 -0
  78. package/dist/middleware/protect.d.ts.map +1 -0
  79. package/dist/middleware/rate-limit-sliding.d.ts.map +1 -1
  80. package/dist/middleware/rate-limit-token.d.ts.map +1 -1
  81. package/dist/middleware/rate-limit.d.ts.map +1 -1
  82. package/dist/middleware/response-splitting.d.ts +83 -0
  83. package/dist/middleware/response-splitting.d.ts.map +1 -0
  84. package/dist/middleware/sveltekit.d.ts +68 -0
  85. package/dist/middleware/sveltekit.d.ts.map +1 -0
  86. package/dist/middleware/token-budget.d.ts +75 -0
  87. package/dist/middleware/token-budget.d.ts.map +1 -0
  88. package/dist/nestjs/index.js +1724 -0
  89. package/dist/nestjs/index.js.map +1 -0
  90. package/dist/nestjs/index.mjs +1717 -0
  91. package/dist/nestjs/index.mjs.map +1 -0
  92. package/dist/nextjs/index.js +6184 -0
  93. package/dist/nextjs/index.js.map +1 -0
  94. package/dist/nextjs/index.mjs +6178 -0
  95. package/dist/nextjs/index.mjs.map +1 -0
  96. package/dist/nuxt/index.js +6141 -0
  97. package/dist/nuxt/index.js.map +1 -0
  98. package/dist/nuxt/index.mjs +6136 -0
  99. package/dist/nuxt/index.mjs.map +1 -0
  100. package/dist/sanitizers/encode.d.ts.map +1 -1
  101. package/dist/sanitizers/graphql.d.ts +72 -0
  102. package/dist/sanitizers/graphql.d.ts.map +1 -0
  103. package/dist/sanitizers/headers.d.ts +18 -0
  104. package/dist/sanitizers/headers.d.ts.map +1 -1
  105. package/dist/sanitizers/index.d.ts +4 -1
  106. package/dist/sanitizers/index.d.ts.map +1 -1
  107. package/dist/sanitizers/index.js +140 -66
  108. package/dist/sanitizers/index.js.map +1 -1
  109. package/dist/sanitizers/index.mjs +135 -67
  110. package/dist/sanitizers/index.mjs.map +1 -1
  111. package/dist/sanitizers/prompt-injection.d.ts +62 -0
  112. package/dist/sanitizers/prompt-injection.d.ts.map +1 -0
  113. package/dist/sanitizers/sanitize.d.ts +1 -1
  114. package/dist/sanitizers/sanitize.d.ts.map +1 -1
  115. package/dist/sanitizers/xpath.d.ts +37 -0
  116. package/dist/sanitizers/xpath.d.ts.map +1 -0
  117. package/dist/stores/index.js +4 -4
  118. package/dist/stores/index.js.map +1 -1
  119. package/dist/stores/index.mjs +4 -4
  120. package/dist/stores/index.mjs.map +1 -1
  121. package/dist/stores/redis.d.ts +7 -1
  122. package/dist/stores/redis.d.ts.map +1 -1
  123. package/dist/sveltekit/index.js +6142 -0
  124. package/dist/sveltekit/index.js.map +1 -0
  125. package/dist/sveltekit/index.mjs +6137 -0
  126. package/dist/sveltekit/index.mjs.map +1 -0
  127. package/dist/validation/index.d.ts +2 -0
  128. package/dist/validation/index.d.ts.map +1 -1
  129. package/dist/validation/index.js +137 -12
  130. package/dist/validation/index.js.map +1 -1
  131. package/dist/validation/index.mjs +116 -13
  132. package/dist/validation/index.mjs.map +1 -1
  133. package/dist/validation/redirect.d.ts.map +1 -1
  134. package/dist/validation/schema.d.ts.map +1 -1
  135. package/dist/validation/url-async.d.ts +137 -0
  136. package/dist/validation/url-async.d.ts.map +1 -0
  137. package/package.json +57 -12
  138. package/scripts/postinstall.cjs +26 -0
  139. package/dist/cli/arcis.d.ts +0 -23
  140. package/dist/cli/arcis.d.ts.map +0 -1
  141. package/dist/cli/arcis.js +0 -312
  142. package/dist/cli/arcis.js.map +0 -1
  143. package/dist/cli/arcis.mjs +0 -309
  144. package/dist/cli/arcis.mjs.map +0 -1
@@ -65,8 +65,8 @@ var XSS_REMOVE_PATTERNS = [
65
65
  /** javascript: and vbscript: protocols (allow optional spaces before colon) */
66
66
  /javascript\s*:/gi,
67
67
  /vbscript\s*:/gi,
68
- /** data: URIs with HTML/script content */
69
- /data\s*:\s*text\/html[^>\s]*/gi,
68
+ /** data: URIs with HTML or SVG content (SVG can run JS via inline event handlers) */
69
+ /data\s*:\s*(?:text\/html|image\/svg)[^>\s]*/gi,
70
70
  /** form tag injection — phishing via action= redirection */
71
71
  /<form[\s>][^>]*/gi,
72
72
  /** meta tag injection — http-equiv refresh or CSP bypass */
@@ -591,6 +591,89 @@ function detectXxe(input) {
591
591
  return false;
592
592
  }
593
593
 
594
+ // src/sanitizers/ldap.ts
595
+ var LDAP_FILTER_CHARS = /[*()\\\x00]/g;
596
+ var LDAP_DN_CHARS = /[,+<>;"=\/\\\x00*()\x00]/g;
597
+ var LDAP_DETECT_PATTERN = /[*()\\\x00]/;
598
+ var LDAP_INJECTION_PATTERN = /\)\s*\(|\*\s*\)\s*\(/;
599
+ var escapeChar = (char) => "\\" + char.charCodeAt(0).toString(16).padStart(2, "0");
600
+ function sanitizeLdapFilter(input) {
601
+ if (typeof input !== "string") return String(input);
602
+ return input.replace(LDAP_FILTER_CHARS, escapeChar);
603
+ }
604
+ function sanitizeLdapDn(input) {
605
+ if (typeof input !== "string") return String(input);
606
+ return input.replace(LDAP_DN_CHARS, escapeChar);
607
+ }
608
+ function detectLdapInjection(input) {
609
+ if (typeof input !== "string") return false;
610
+ return LDAP_DETECT_PATTERN.test(input) || LDAP_INJECTION_PATTERN.test(input);
611
+ }
612
+
613
+ // src/sanitizers/xpath.ts
614
+ var XPATH_INJECTION_CHARS = /['"|,()]/;
615
+ var XPATH_INJECTION_PATTERN = /('\s*(or|and)\s*'|"\s*(or|and)\s*"|\)\s*(or|and)\s*\(|\|\s*\/)/i;
616
+ function detectXpathInjection(input) {
617
+ if (typeof input !== "string" || input.length === 0) return false;
618
+ if (!XPATH_INJECTION_CHARS.test(input)) return false;
619
+ return XPATH_INJECTION_PATTERN.test(input);
620
+ }
621
+ function sanitizeXpath(input) {
622
+ if (typeof input !== "string") return String(input);
623
+ return input.replace(/['"|,]/g, "");
624
+ }
625
+
626
+ // src/sanitizers/headers.ts
627
+ var HEADER_INJECTION_PATTERN = /\r\n|\r|\n|\0/g;
628
+ function sanitizeHeaderValue(input, collectThreats = false) {
629
+ if (typeof input !== "string") {
630
+ return collectThreats ? { value: String(input), wasSanitized: false, threats: [] } : String(input);
631
+ }
632
+ const threats = [];
633
+ let wasSanitized = false;
634
+ if (HEADER_INJECTION_PATTERN.test(input)) {
635
+ HEADER_INJECTION_PATTERN.lastIndex = 0;
636
+ wasSanitized = true;
637
+ if (collectThreats) {
638
+ const matches = input.match(HEADER_INJECTION_PATTERN);
639
+ if (matches) {
640
+ for (const match of matches) {
641
+ threats.push({
642
+ type: "header_injection",
643
+ pattern: HEADER_INJECTION_PATTERN.source,
644
+ original: match
645
+ });
646
+ }
647
+ }
648
+ }
649
+ }
650
+ HEADER_INJECTION_PATTERN.lastIndex = 0;
651
+ const value = input.replace(HEADER_INJECTION_PATTERN, "");
652
+ if (collectThreats) {
653
+ return { value, wasSanitized, threats };
654
+ }
655
+ return value;
656
+ }
657
+ function sanitizeHeaders(headers) {
658
+ if (!headers || typeof headers !== "object") {
659
+ return {};
660
+ }
661
+ const result = {};
662
+ for (const [key, value] of Object.entries(headers)) {
663
+ const sanitizedKey = sanitizeHeaderValue(String(key));
664
+ const sanitizedValue = sanitizeHeaderValue(String(value));
665
+ result[sanitizedKey] = sanitizedValue;
666
+ }
667
+ return result;
668
+ }
669
+ function detectHeaderInjection(input) {
670
+ if (typeof input !== "string") return false;
671
+ HEADER_INJECTION_PATTERN.lastIndex = 0;
672
+ return HEADER_INJECTION_PATTERN.test(input);
673
+ }
674
+ var sanitizeEmailHeader = sanitizeHeaderValue;
675
+ var detectEmailHeaderInjection = detectHeaderInjection;
676
+
594
677
  // src/sanitizers/sanitize.ts
595
678
  function sanitizeString(value, options = {}) {
596
679
  if (typeof value !== "string") return value;
@@ -703,6 +786,15 @@ function scanThreats(data, depth = 0) {
703
786
  if (detectCommandInjection(data)) {
704
787
  return { vector: "command", rule: "command/match", matchedPattern: sample };
705
788
  }
789
+ if (detectLdapInjection(data)) {
790
+ return { vector: "ldap", rule: "ldap/match", matchedPattern: sample };
791
+ }
792
+ if (detectXpathInjection(data)) {
793
+ return { vector: "xpath", rule: "xpath/match", matchedPattern: sample };
794
+ }
795
+ if (detectHeaderInjection(data)) {
796
+ return { vector: "header", rule: "header/match", matchedPattern: sample };
797
+ }
706
798
  return null;
707
799
  }
708
800
  function createSanitizer(options = {}) {
@@ -837,55 +929,6 @@ function detectJsonpInjection(callback) {
837
929
  return false;
838
930
  }
839
931
 
840
- // src/sanitizers/headers.ts
841
- var HEADER_INJECTION_PATTERN = /\r\n|\r|\n|\0/g;
842
- function sanitizeHeaderValue(input, collectThreats = false) {
843
- if (typeof input !== "string") {
844
- return collectThreats ? { value: String(input), wasSanitized: false, threats: [] } : String(input);
845
- }
846
- const threats = [];
847
- let wasSanitized = false;
848
- if (HEADER_INJECTION_PATTERN.test(input)) {
849
- HEADER_INJECTION_PATTERN.lastIndex = 0;
850
- wasSanitized = true;
851
- if (collectThreats) {
852
- const matches = input.match(HEADER_INJECTION_PATTERN);
853
- if (matches) {
854
- for (const match of matches) {
855
- threats.push({
856
- type: "header_injection",
857
- pattern: HEADER_INJECTION_PATTERN.source,
858
- original: match
859
- });
860
- }
861
- }
862
- }
863
- }
864
- HEADER_INJECTION_PATTERN.lastIndex = 0;
865
- const value = input.replace(HEADER_INJECTION_PATTERN, "");
866
- if (collectThreats) {
867
- return { value, wasSanitized, threats };
868
- }
869
- return value;
870
- }
871
- function sanitizeHeaders(headers) {
872
- if (!headers || typeof headers !== "object") {
873
- return {};
874
- }
875
- const result = {};
876
- for (const [key, value] of Object.entries(headers)) {
877
- const sanitizedKey = sanitizeHeaderValue(String(key));
878
- const sanitizedValue = sanitizeHeaderValue(String(value));
879
- result[sanitizedKey] = sanitizedValue;
880
- }
881
- return result;
882
- }
883
- function detectHeaderInjection(input) {
884
- if (typeof input !== "string") return false;
885
- HEADER_INJECTION_PATTERN.lastIndex = 0;
886
- return HEADER_INJECTION_PATTERN.test(input);
887
- }
888
-
889
932
  // src/sanitizers/pii.ts
890
933
  var EMAIL_RE = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z]{2,})+/g;
891
934
  var PHONE_RE = /(?<!\d)(?:\+?1[-.\s]?)?\(?[2-9]\d{2}\)?[-.\s]?\d{3}[-.\s]?\d{4}(?!\d)/g;
@@ -1051,6 +1094,7 @@ function encodeForJs(value) {
1051
1094
  let result = "";
1052
1095
  for (const char of value) {
1053
1096
  const cp = char.codePointAt(0);
1097
+ if (cp === void 0) continue;
1054
1098
  if (cp >= 48 && cp <= 57 || // 0-9
1055
1099
  cp >= 65 && cp <= 90 || // A-Z
1056
1100
  cp >= 97 && cp <= 122) {
@@ -1087,25 +1131,49 @@ function encodeForCss(value) {
1087
1131
  return result;
1088
1132
  }
1089
1133
 
1090
- // src/sanitizers/ldap.ts
1091
- var LDAP_FILTER_CHARS = /[*()\\\x00]/g;
1092
- var LDAP_DN_CHARS = /[,+<>;"=\/\\\x00*()\x00]/g;
1093
- var LDAP_DETECT_PATTERN = /[*()\\\x00]/;
1094
- var LDAP_INJECTION_PATTERN = /\)\s*\(|\*\s*\)\s*\(/;
1095
- var escapeChar = (char) => "\\" + char.charCodeAt(0).toString(16).padStart(2, "0");
1096
- function sanitizeLdapFilter(input) {
1097
- if (typeof input !== "string") return String(input);
1098
- return input.replace(LDAP_FILTER_CHARS, escapeChar);
1134
+ // src/sanitizers/graphql.ts
1135
+ var DEFAULTS = {
1136
+ maxDepth: 10,
1137
+ maxLength: 1e4,
1138
+ blockIntrospection: true
1139
+ };
1140
+ var INTROSPECTION_PATTERN = /\b__(schema|type|typeKind|directive)\b/;
1141
+ function computeDepth(query) {
1142
+ let depth = 0;
1143
+ let max = 0;
1144
+ for (let i = 0; i < query.length; i++) {
1145
+ const c = query.charCodeAt(i);
1146
+ if (c === 123) {
1147
+ depth++;
1148
+ if (depth > max) max = depth;
1149
+ } else if (c === 125) {
1150
+ if (depth > 0) depth--;
1151
+ }
1152
+ }
1153
+ return max;
1099
1154
  }
1100
- function sanitizeLdapDn(input) {
1101
- if (typeof input !== "string") return String(input);
1102
- return input.replace(LDAP_DN_CHARS, escapeChar);
1155
+ function inspectGraphqlQuery(query, options = {}) {
1156
+ const maxDepth = options.maxDepth ?? DEFAULTS.maxDepth;
1157
+ const maxLength = options.maxLength ?? DEFAULTS.maxLength;
1158
+ const blockIntrospection = options.blockIntrospection ?? DEFAULTS.blockIntrospection;
1159
+ const length = query.length;
1160
+ const depth = computeDepth(query);
1161
+ if (depth > maxDepth) {
1162
+ return { blocked: true, reason: "depth", depth, length };
1163
+ }
1164
+ if (blockIntrospection && INTROSPECTION_PATTERN.test(query)) {
1165
+ return { blocked: true, reason: "introspection", depth, length };
1166
+ }
1167
+ if (length > maxLength) {
1168
+ return { blocked: true, reason: "length", depth, length };
1169
+ }
1170
+ return { blocked: false, depth, length };
1103
1171
  }
1104
- function detectLdapInjection(input) {
1105
- if (typeof input !== "string") return false;
1106
- return LDAP_DETECT_PATTERN.test(input) || LDAP_INJECTION_PATTERN.test(input);
1172
+ function detectGraphqlAbuse(query, options) {
1173
+ if (typeof query !== "string" || query.length === 0) return false;
1174
+ return inspectGraphqlQuery(query, options).blocked;
1107
1175
  }
1108
1176
 
1109
- 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, scanThreats };
1177
+ export { createSanitizer, detectCommandInjection, detectEmailHeaderInjection, detectGraphqlAbuse, detectHeaderInjection, detectJsonpInjection, detectLdapInjection, detectNoSqlInjection, detectPathTraversal, detectPii, detectPrototypePollution, detectSql, detectSsti, detectXpathInjection, detectXss, detectXxe, encodeForAttribute, encodeForCss, encodeForHtml, encodeForJs, encodeForUrl, encodeHtmlEntities, getDangerousOperators, getDangerousProtoKeys, inspectGraphqlQuery, isDangerousNoSqlKey, isDangerousProtoKey, isPlainObject, redactObjectPii, redactPii, sanitizeCommand, sanitizeEmailHeader, sanitizeHeaderValue, sanitizeHeaders, sanitizeJsonpCallback, sanitizeLdapDn, sanitizeLdapFilter, sanitizeObject, sanitizePath, sanitizeSql, sanitizeSsti, sanitizeString, sanitizeXpath, sanitizeXss, sanitizeXxe, scanObjectPii, scanPii, scanThreats };
1110
1178
  //# sourceMappingURL=index.mjs.map
1111
1179
  //# sourceMappingURL=index.mjs.map