@arcis/node 1.5.2 → 1.6.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 (66) hide show
  1. package/README.md +48 -7
  2. package/dist/astro/index.js.map +1 -1
  3. package/dist/astro/index.mjs.map +1 -1
  4. package/dist/bun/index.js.map +1 -1
  5. package/dist/bun/index.mjs.map +1 -1
  6. package/dist/core/constants.d.ts +2 -2
  7. package/dist/core/constants.d.ts.map +1 -1
  8. package/dist/core/index.js +19 -1
  9. package/dist/core/index.js.map +1 -1
  10. package/dist/core/index.mjs +19 -1
  11. package/dist/core/index.mjs.map +1 -1
  12. package/dist/fastify/index.js.map +1 -1
  13. package/dist/fastify/index.mjs.map +1 -1
  14. package/dist/hono/index.js.map +1 -1
  15. package/dist/hono/index.mjs.map +1 -1
  16. package/dist/index.d.ts +3 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +407 -8
  19. package/dist/index.js.map +1 -1
  20. package/dist/index.mjs +407 -9
  21. package/dist/index.mjs.map +1 -1
  22. package/dist/koa/index.js.map +1 -1
  23. package/dist/koa/index.mjs.map +1 -1
  24. package/dist/logging/index.js.map +1 -1
  25. package/dist/logging/index.mjs.map +1 -1
  26. package/dist/middleware/correlation.d.ts +87 -0
  27. package/dist/middleware/correlation.d.ts.map +1 -0
  28. package/dist/middleware/graphql.d.ts.map +1 -1
  29. package/dist/middleware/index.d.ts +3 -1
  30. package/dist/middleware/index.d.ts.map +1 -1
  31. package/dist/middleware/index.js +366 -8
  32. package/dist/middleware/index.js.map +1 -1
  33. package/dist/middleware/index.mjs +366 -9
  34. package/dist/middleware/index.mjs.map +1 -1
  35. package/dist/middleware/protect.d.ts +32 -0
  36. package/dist/middleware/protect.d.ts.map +1 -1
  37. package/dist/nestjs/index.js +55 -2
  38. package/dist/nestjs/index.js.map +1 -1
  39. package/dist/nestjs/index.mjs +55 -2
  40. package/dist/nestjs/index.mjs.map +1 -1
  41. package/dist/nextjs/index.js.map +1 -1
  42. package/dist/nextjs/index.mjs.map +1 -1
  43. package/dist/nuxt/index.js.map +1 -1
  44. package/dist/nuxt/index.mjs.map +1 -1
  45. package/dist/sanitizers/deserialization.d.ts +30 -0
  46. package/dist/sanitizers/deserialization.d.ts.map +1 -0
  47. package/dist/sanitizers/graphql.d.ts +20 -3
  48. package/dist/sanitizers/graphql.d.ts.map +1 -1
  49. package/dist/sanitizers/index.d.ts +2 -0
  50. package/dist/sanitizers/index.d.ts.map +1 -1
  51. package/dist/sanitizers/index.js +150 -7
  52. package/dist/sanitizers/index.js.map +1 -1
  53. package/dist/sanitizers/index.mjs +149 -8
  54. package/dist/sanitizers/index.mjs.map +1 -1
  55. package/dist/sanitizers/prompt-injection.d.ts.map +1 -1
  56. package/dist/sanitizers/sanitize.d.ts +0 -20
  57. package/dist/sanitizers/sanitize.d.ts.map +1 -1
  58. package/dist/stores/index.js.map +1 -1
  59. package/dist/stores/index.mjs.map +1 -1
  60. package/dist/sveltekit/index.js.map +1 -1
  61. package/dist/sveltekit/index.mjs.map +1 -1
  62. package/dist/validation/index.js +55 -2
  63. package/dist/validation/index.js.map +1 -1
  64. package/dist/validation/index.mjs +55 -2
  65. package/dist/validation/index.mjs.map +1 -1
  66. package/package.json +2 -2
package/dist/index.d.ts CHANGED
@@ -46,9 +46,11 @@ export type { MethodAllowlistOptions } from './middleware/method-allowlist';
46
46
  export { massAssign } from './middleware/mass-assign';
47
47
  export type { MassAssignOptions } from './middleware/mass-assign';
48
48
  export { protectLogin, protectSignup, protectApi } from './middleware/protect';
49
- export type { ProtectLoginOptions, ProtectSignupOptions, ProtectApiOptions, } from './middleware/protect';
49
+ export type { ProtectLoginOptions, ProtectSignupOptions, ProtectApiOptions, CorrelationOptions, } from './middleware/protect';
50
50
  export { graphqlGuard } from './middleware/graphql';
51
51
  export type { GraphqlGuardMiddlewareOptions } from './middleware/graphql';
52
+ export { CorrelationWindow } from './middleware/correlation';
53
+ export type { CorrelationEvent, CorrelationDetections, CorrelationWindowOptions, } from './middleware/correlation';
52
54
  export { inspectGraphqlQuery, detectGraphqlAbuse, } from './sanitizers/graphql';
53
55
  export type { GraphqlGuardOptions, GraphqlGuardResult, GraphqlViolation, } from './sanitizers/graphql';
54
56
  export { Guards } from './guards';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -165,7 +165,16 @@ var SQL_PATTERNS = [
165
165
  /** Time-based blind: PostgreSQL pg_sleep() */
166
166
  /\bpg_sleep\s*\(/gi,
167
167
  /** Time-based blind: MSSQL WAITFOR DELAY */
168
- /\bWAITFOR\s+DELAY\b/gi
168
+ /\bWAITFOR\s+DELAY\b/gi,
169
+ /**
170
+ * Oracle DBMS_* stdlib packages used for time-based blind SQLi
171
+ * (DBMS_LOCK.SLEEP, DBMS_PIPE.RECEIVE_MESSAGE) and other Oracle
172
+ * abuse paths. No legitimate user input contains these. Mirrors
173
+ * `sqli-oracle-dbms-packages` in packages/core/patterns.json —
174
+ * improvements.md §1.1.e Q3. Must stay in sync until Node
175
+ * migrates to patterns.json-at-runtime (planned v1.7).
176
+ */
177
+ /\bDBMS_(?:LOCK|PIPE|UTILITY|XSLPROCESSOR|JAVA|OUTPUT|SCHEDULER)\b/gi
169
178
  ];
170
179
  var PATH_PATTERNS = [
171
180
  /** Unix path traversal */
@@ -203,6 +212,15 @@ var COMMAND_PATTERNS = [
203
212
  /[;&|`]/g,
204
213
  /** Command substitution: $( ... ) — matched as a pair to reduce false positives */
205
214
  /\$\(/g,
215
+ /**
216
+ * POSIX shell IFS-substitution: ${IFS} or ${IFS%??}.
217
+ * Attackers use this to inject spaces past metacharacter filters
218
+ * in payloads like `;cat${IFS}/etc/passwd`. Mirrors
219
+ * `cmdi-ifs-bypass` in packages/core/patterns.json — improvements.md
220
+ * §1.1.e Q5. Must stay in sync until Node migrates to
221
+ * patterns.json-at-runtime (planned v1.7).
222
+ */
223
+ /\$\{IFS(?:%[^}]*)?\}/g,
206
224
  /** URL-encoded control characters (%00-%0F): null, tab, vtab, formfeed, LF, CR */
207
225
  /%0[0-9a-f]/gi
208
226
  ];
@@ -1147,6 +1165,40 @@ function detectHeaderInjection(input) {
1147
1165
  }
1148
1166
 
1149
1167
  // src/sanitizers/sanitize.ts
1168
+ function multiDecode(value, maxPasses = 4) {
1169
+ for (let i = 0; i < maxPasses; i++) {
1170
+ const prev = value;
1171
+ try {
1172
+ value = decodeURIComponent(value);
1173
+ } catch {
1174
+ }
1175
+ value = htmlEntityDecode(value);
1176
+ if (value === prev) break;
1177
+ }
1178
+ return value;
1179
+ }
1180
+ function htmlEntityDecode(s) {
1181
+ s = s.replace(/&#(\d+);/g, (_m, n) => {
1182
+ const code = parseInt(n, 10);
1183
+ return Number.isFinite(code) && code >= 0 && code <= 1114111 ? String.fromCodePoint(code) : _m;
1184
+ });
1185
+ s = s.replace(/&#x([0-9a-fA-F]+);/g, (_m, h) => {
1186
+ const code = parseInt(h, 16);
1187
+ return Number.isFinite(code) && code >= 0 && code <= 1114111 ? String.fromCodePoint(code) : _m;
1188
+ });
1189
+ const named = {
1190
+ "&lt;": "<",
1191
+ "&gt;": ">",
1192
+ "&amp;": "&",
1193
+ "&quot;": '"',
1194
+ "&apos;": "'",
1195
+ "&nbsp;": " "
1196
+ };
1197
+ for (const [entity, ch] of Object.entries(named)) {
1198
+ s = s.split(entity).join(ch);
1199
+ }
1200
+ return s;
1201
+ }
1150
1202
  function sanitizeString(value, options = {}) {
1151
1203
  if (typeof value !== "string") return value;
1152
1204
  const maxSize = options.maxSize ?? INPUT.DEFAULT_MAX_SIZE;
@@ -1154,7 +1206,8 @@ function sanitizeString(value, options = {}) {
1154
1206
  throw new InputTooLargeError(maxSize, value.length);
1155
1207
  }
1156
1208
  const reject = options.mode === "reject";
1157
- let result = value;
1209
+ let result = value.normalize("NFKC");
1210
+ result = multiDecode(result);
1158
1211
  if (options.sql !== false) {
1159
1212
  if (reject) {
1160
1213
  if (detectSql(result)) {
@@ -1601,7 +1654,9 @@ function encodeForCss(value) {
1601
1654
  var DEFAULTS = {
1602
1655
  maxDepth: 10,
1603
1656
  maxLength: 1e4,
1604
- blockIntrospection: true
1657
+ blockIntrospection: true,
1658
+ maxAliases: 50,
1659
+ blockFragmentCycles: true
1605
1660
  };
1606
1661
  var INTROSPECTION_PATTERN = /\b__(schema|type|typeKind|directive)\b/;
1607
1662
  function computeDepth(query) {
@@ -1618,22 +1673,87 @@ function computeDepth(query) {
1618
1673
  }
1619
1674
  return max;
1620
1675
  }
1676
+ var ALIAS_PATTERN = /\b([a-zA-Z_][a-zA-Z0-9_]*)\s*:\s*([a-zA-Z_][a-zA-Z0-9_]*)\b/g;
1677
+ var FRAGMENT_DEF_PATTERN = /\bfragment\s+([a-zA-Z_][a-zA-Z0-9_]*)\s+on\s+[a-zA-Z_][a-zA-Z0-9_]*\s*\{/g;
1678
+ var FRAGMENT_SPREAD_PATTERN = /\.\.\.\s*([a-zA-Z_][a-zA-Z0-9_]*)\b/g;
1679
+ function countAliases(query) {
1680
+ let n = 0;
1681
+ ALIAS_PATTERN.lastIndex = 0;
1682
+ while (ALIAS_PATTERN.exec(query) !== null) n++;
1683
+ return n;
1684
+ }
1685
+ function hasFragmentCycle(query) {
1686
+ const deps = /* @__PURE__ */ new Map();
1687
+ FRAGMENT_DEF_PATTERN.lastIndex = 0;
1688
+ let match;
1689
+ while ((match = FRAGMENT_DEF_PATTERN.exec(query)) !== null) {
1690
+ const name = match[1];
1691
+ const bodyStart = match.index + match[0].length;
1692
+ let depth = 1;
1693
+ let i = bodyStart;
1694
+ while (i < query.length && depth > 0) {
1695
+ const ch = query[i];
1696
+ if (ch === "{") depth++;
1697
+ else if (ch === "}") depth--;
1698
+ i++;
1699
+ }
1700
+ const bodyEnd = depth === 0 ? i - 1 : i;
1701
+ const body = query.slice(bodyStart, bodyEnd);
1702
+ const spreads = /* @__PURE__ */ new Set();
1703
+ FRAGMENT_SPREAD_PATTERN.lastIndex = 0;
1704
+ let sm;
1705
+ while ((sm = FRAGMENT_SPREAD_PATTERN.exec(body)) !== null) {
1706
+ spreads.add(sm[1]);
1707
+ }
1708
+ deps.set(name, spreads);
1709
+ }
1710
+ if (deps.size === 0) return false;
1711
+ const WHITE = 0;
1712
+ const GRAY = 1;
1713
+ const BLACK = 2;
1714
+ const color = /* @__PURE__ */ new Map();
1715
+ for (const name of deps.keys()) color.set(name, WHITE);
1716
+ function visit(name) {
1717
+ if (color.get(name) === GRAY) return true;
1718
+ if (color.get(name) === BLACK) return false;
1719
+ if (!deps.has(name)) return false;
1720
+ color.set(name, GRAY);
1721
+ for (const child of deps.get(name)) {
1722
+ if (visit(child)) return true;
1723
+ }
1724
+ color.set(name, BLACK);
1725
+ return false;
1726
+ }
1727
+ for (const name of deps.keys()) {
1728
+ if (visit(name)) return true;
1729
+ }
1730
+ return false;
1731
+ }
1621
1732
  function inspectGraphqlQuery(query, options = {}) {
1622
1733
  const maxDepth = options.maxDepth ?? DEFAULTS.maxDepth;
1623
1734
  const maxLength = options.maxLength ?? DEFAULTS.maxLength;
1624
1735
  const blockIntrospection = options.blockIntrospection ?? DEFAULTS.blockIntrospection;
1736
+ const maxAliases = options.maxAliases ?? DEFAULTS.maxAliases;
1737
+ const blockFragmentCycles = options.blockFragmentCycles ?? DEFAULTS.blockFragmentCycles;
1625
1738
  const length = query.length;
1626
1739
  const depth = computeDepth(query);
1740
+ const aliases = countAliases(query);
1627
1741
  if (depth > maxDepth) {
1628
- return { blocked: true, reason: "depth", depth, length };
1742
+ return { blocked: true, reason: "depth", depth, length, aliases };
1629
1743
  }
1630
1744
  if (blockIntrospection && INTROSPECTION_PATTERN.test(query)) {
1631
- return { blocked: true, reason: "introspection", depth, length };
1745
+ return { blocked: true, reason: "introspection", depth, length, aliases };
1746
+ }
1747
+ if (aliases > maxAliases) {
1748
+ return { blocked: true, reason: "aliases", depth, length, aliases };
1749
+ }
1750
+ if (blockFragmentCycles && hasFragmentCycle(query)) {
1751
+ return { blocked: true, reason: "fragment_cycle", depth, length, aliases };
1632
1752
  }
1633
1753
  if (length > maxLength) {
1634
- return { blocked: true, reason: "length", depth, length };
1754
+ return { blocked: true, reason: "length", depth, length, aliases };
1635
1755
  }
1636
- return { blocked: false, depth, length };
1756
+ return { blocked: false, depth, length, aliases };
1637
1757
  }
1638
1758
  function detectGraphqlAbuse(query, options) {
1639
1759
  if (typeof query !== "string" || query.length === 0) return false;
@@ -9969,6 +10089,46 @@ function signupProtection(options = {}) {
9969
10089
  }
9970
10090
 
9971
10091
  // src/middleware/protect.ts
10092
+ function getClientIp(req) {
10093
+ const xff = req?.headers?.["x-forwarded-for"] ?? req?.headers?.["X-Forwarded-For"];
10094
+ if (typeof xff === "string" && xff.length > 0) {
10095
+ const first = xff.split(",")[0]?.trim();
10096
+ if (first) return first;
10097
+ }
10098
+ if (typeof req?.ip === "string") return req.ip;
10099
+ const remote = req?.socket?.remoteAddress;
10100
+ return typeof remote === "string" ? remote : "";
10101
+ }
10102
+ function correlationMiddleware(opts) {
10103
+ const vector = opts.vector ?? "request";
10104
+ const usernameField = opts.usernameField ?? "username";
10105
+ const statusCode = opts.statusCode ?? 429;
10106
+ const message = opts.message ?? "Suspicious request pattern detected.";
10107
+ return function(req, res, next) {
10108
+ const ip = getClientIp(req);
10109
+ if (!ip) return next();
10110
+ const route = opts.route ?? (req.path || req.url || "/");
10111
+ const username = req?.body?.[usernameField];
10112
+ const distinctValue = typeof username === "string" && username.length > 0 ? username : void 0;
10113
+ const detections = opts.window.record(
10114
+ ip,
10115
+ vector,
10116
+ route,
10117
+ req.method || "GET",
10118
+ distinctValue
10119
+ );
10120
+ if (detections.scanner || detections.credentialStuffing || detections.raceWindow) {
10121
+ res.status(statusCode).json({
10122
+ error: message,
10123
+ scanner: detections.scanner,
10124
+ credential_stuffing: detections.credentialStuffing,
10125
+ race_window: detections.raceWindow
10126
+ });
10127
+ return;
10128
+ }
10129
+ next();
10130
+ };
10131
+ }
9972
10132
  function resolve(override, defaults) {
9973
10133
  if (override === false) return null;
9974
10134
  if (override === void 0) return defaults;
@@ -9988,6 +10148,11 @@ function protectLogin(options = {}) {
9988
10148
  if (csrf) middlewares.push(csrfProtection(csrf));
9989
10149
  const sanitize = resolve(options.sanitize, {});
9990
10150
  if (sanitize) middlewares.push(createSanitizer(sanitize));
10151
+ if (options.correlation) {
10152
+ middlewares.push(
10153
+ correlationMiddleware({ vector: "login", ...options.correlation })
10154
+ );
10155
+ }
9991
10156
  return middlewares;
9992
10157
  }
9993
10158
  function protectSignup(options = {}) {
@@ -10004,6 +10169,11 @@ function protectSignup(options = {}) {
10004
10169
  if (sanitize) middlewares.push(createSanitizer(sanitize));
10005
10170
  const signup = resolve(options.signup, {});
10006
10171
  if (signup) middlewares.push(signupProtection(signup));
10172
+ if (options.correlation) {
10173
+ middlewares.push(
10174
+ correlationMiddleware({ vector: "signup", ...options.correlation })
10175
+ );
10176
+ }
10007
10177
  return middlewares;
10008
10178
  }
10009
10179
  function protectApi(options = {}) {
@@ -10014,6 +10184,11 @@ function protectApi(options = {}) {
10014
10184
  if (cors) middlewares.push(safeCors(cors));
10015
10185
  const sanitize = resolve(options.sanitize, {});
10016
10186
  if (sanitize) middlewares.push(createSanitizer(sanitize));
10187
+ if (options.correlation) {
10188
+ middlewares.push(
10189
+ correlationMiddleware({ vector: "api", ...options.correlation })
10190
+ );
10191
+ }
10017
10192
  return middlewares;
10018
10193
  }
10019
10194
 
@@ -10021,7 +10196,9 @@ function protectApi(options = {}) {
10021
10196
  var DEFAULT_MESSAGES = {
10022
10197
  depth: "Query exceeds maximum nesting depth",
10023
10198
  length: "Query exceeds maximum length",
10024
- introspection: "Introspection queries are disabled"
10199
+ introspection: "Introspection queries are disabled",
10200
+ aliases: "Query exceeds maximum alias count (alias-bomb protection)",
10201
+ fragment_cycle: "Query contains a cyclic fragment definition"
10025
10202
  };
10026
10203
  function extractQuery(req) {
10027
10204
  const bodyQuery = typeof req.body === "object" && req.body !== null ? req.body.query : void 0;
@@ -10057,6 +10234,186 @@ function graphqlGuard(options = {}) {
10057
10234
  };
10058
10235
  }
10059
10236
 
10237
+ // src/middleware/correlation.ts
10238
+ var EMPTY_DETECTIONS = Object.freeze({
10239
+ scanner: false,
10240
+ credentialStuffing: false,
10241
+ raceWindow: false,
10242
+ distinctVectors: 0,
10243
+ distinctValues: 0,
10244
+ requestsInWindow: 0
10245
+ });
10246
+ function normalizePair(a, b) {
10247
+ return a < b ? `${a}${b}` : `${b}${a}`;
10248
+ }
10249
+ var CorrelationWindow = class {
10250
+ constructor(options = {}) {
10251
+ // Map iteration order in JS is insertion order, so re-inserting on
10252
+ // access gives us LRU behaviour without a separate linked list.
10253
+ this.buckets = /* @__PURE__ */ new Map();
10254
+ const {
10255
+ windowSeconds = 60,
10256
+ maxIps = 1e4,
10257
+ maxEventsPerIp = 200,
10258
+ scannerDistinctVectors = 3,
10259
+ scannerMinRequests = 20,
10260
+ credentialStuffingDistinctValues = 10,
10261
+ raceWindowMs = 200,
10262
+ racePairs
10263
+ } = options;
10264
+ if (windowSeconds <= 0) throw new Error("windowSeconds must be > 0");
10265
+ if (maxIps < 1) throw new Error("maxIps must be >= 1");
10266
+ if (maxEventsPerIp < 1) throw new Error("maxEventsPerIp must be >= 1");
10267
+ this.windowSeconds = windowSeconds;
10268
+ this.maxIps = maxIps;
10269
+ this.maxEventsPerIp = maxEventsPerIp;
10270
+ this.scannerDistinctVectors = scannerDistinctVectors;
10271
+ this.scannerMinRequests = scannerMinRequests;
10272
+ this.csDistinctValues = credentialStuffingDistinctValues;
10273
+ this.raceWindowSeconds = raceWindowMs / 1e3;
10274
+ this.racePairKeys = /* @__PURE__ */ new Set();
10275
+ this.racePairTuples = [];
10276
+ if (racePairs) {
10277
+ for (const [a, b] of racePairs) {
10278
+ const key = normalizePair(a, b);
10279
+ if (!this.racePairKeys.has(key)) {
10280
+ this.racePairKeys.add(key);
10281
+ const sorted = a < b ? [a, b] : [b, a];
10282
+ this.racePairTuples.push(sorted);
10283
+ }
10284
+ }
10285
+ }
10286
+ }
10287
+ record(ip, vector, route, method = "GET", distinctValue, now) {
10288
+ if (!ip) return EMPTY_DETECTIONS;
10289
+ const ts = now ?? Date.now() / 1e3;
10290
+ const event = {
10291
+ timestamp: ts,
10292
+ vector,
10293
+ route,
10294
+ method,
10295
+ distinctValue
10296
+ };
10297
+ let bucket = this.buckets.get(ip);
10298
+ if (bucket === void 0) {
10299
+ bucket = { events: [] };
10300
+ this.buckets.set(ip, bucket);
10301
+ while (this.buckets.size > this.maxIps) {
10302
+ const oldest = this.buckets.keys().next().value;
10303
+ if (oldest === void 0) break;
10304
+ this.buckets.delete(oldest);
10305
+ }
10306
+ } else {
10307
+ this.buckets.delete(ip);
10308
+ this.buckets.set(ip, bucket);
10309
+ }
10310
+ bucket.events.push(event);
10311
+ this.evictStale(bucket, ts);
10312
+ return this.evaluate(bucket, route);
10313
+ }
10314
+ detectScanner(ip, now) {
10315
+ const bucket = this.buckets.get(ip);
10316
+ if (bucket === void 0) return false;
10317
+ this.evictStale(bucket, now ?? Date.now() / 1e3);
10318
+ return this.isScanner(bucket);
10319
+ }
10320
+ detectCredentialStuffing(ip, route, now) {
10321
+ const bucket = this.buckets.get(ip);
10322
+ if (bucket === void 0) return false;
10323
+ this.evictStale(bucket, now ?? Date.now() / 1e3);
10324
+ return this.isCredentialStuffing(bucket, route);
10325
+ }
10326
+ detectRaceWindow(ip, routePair, now) {
10327
+ const bucket = this.buckets.get(ip);
10328
+ if (bucket === void 0) return false;
10329
+ this.evictStale(bucket, now ?? Date.now() / 1e3);
10330
+ const sorted = routePair[0] < routePair[1] ? routePair : [routePair[1], routePair[0]];
10331
+ return this.racePairInBucket(bucket, sorted);
10332
+ }
10333
+ reset(ip) {
10334
+ if (ip === void 0) {
10335
+ this.buckets.clear();
10336
+ } else {
10337
+ this.buckets.delete(ip);
10338
+ }
10339
+ }
10340
+ stats() {
10341
+ let events = 0;
10342
+ for (const b of this.buckets.values()) events += b.events.length;
10343
+ return { trackedIps: this.buckets.size, eventsInWindow: events };
10344
+ }
10345
+ // -------------------------------------------------------- internals
10346
+ evictStale(bucket, now) {
10347
+ const cutoff = now - this.windowSeconds;
10348
+ let drop = 0;
10349
+ while (drop < bucket.events.length && bucket.events[drop].timestamp < cutoff) {
10350
+ drop++;
10351
+ }
10352
+ if (drop > 0) bucket.events.splice(0, drop);
10353
+ if (bucket.events.length > this.maxEventsPerIp) {
10354
+ bucket.events.splice(0, bucket.events.length - this.maxEventsPerIp);
10355
+ }
10356
+ }
10357
+ evaluate(bucket, route) {
10358
+ const vectors = /* @__PURE__ */ new Set();
10359
+ const values = /* @__PURE__ */ new Set();
10360
+ for (const e of bucket.events) {
10361
+ vectors.add(e.vector);
10362
+ if (e.route === route && e.distinctValue !== void 0) {
10363
+ values.add(e.distinctValue);
10364
+ }
10365
+ }
10366
+ return {
10367
+ scanner: this.isScanner(bucket),
10368
+ credentialStuffing: this.isCredentialStuffing(bucket, route),
10369
+ raceWindow: this.isRaceAny(bucket),
10370
+ distinctVectors: vectors.size,
10371
+ distinctValues: values.size,
10372
+ requestsInWindow: bucket.events.length
10373
+ };
10374
+ }
10375
+ isScanner(bucket) {
10376
+ if (bucket.events.length < this.scannerMinRequests) return false;
10377
+ const vectors = /* @__PURE__ */ new Set();
10378
+ for (const e of bucket.events) vectors.add(e.vector);
10379
+ return vectors.size >= this.scannerDistinctVectors;
10380
+ }
10381
+ isCredentialStuffing(bucket, route) {
10382
+ const values = /* @__PURE__ */ new Set();
10383
+ for (const e of bucket.events) {
10384
+ if (e.route === route && e.distinctValue !== void 0) {
10385
+ values.add(e.distinctValue);
10386
+ }
10387
+ }
10388
+ return values.size >= this.csDistinctValues;
10389
+ }
10390
+ racePairInBucket(bucket, sorted) {
10391
+ const [a, b] = sorted;
10392
+ const aTs = [];
10393
+ const bTs = [];
10394
+ for (const e of bucket.events) {
10395
+ if (e.route === a) aTs.push(e.timestamp);
10396
+ else if (e.route === b) bTs.push(e.timestamp);
10397
+ }
10398
+ if (aTs.length === 0 || bTs.length === 0) return false;
10399
+ let ai = 0;
10400
+ let bi = 0;
10401
+ while (ai < aTs.length && bi < bTs.length) {
10402
+ const diff = aTs[ai] - bTs[bi];
10403
+ if (Math.abs(diff) <= this.raceWindowSeconds) return true;
10404
+ if (diff < 0) ai++;
10405
+ else bi++;
10406
+ }
10407
+ return false;
10408
+ }
10409
+ isRaceAny(bucket) {
10410
+ for (const pair of this.racePairTuples) {
10411
+ if (this.racePairInBucket(bucket, pair)) return true;
10412
+ }
10413
+ return false;
10414
+ }
10415
+ };
10416
+
10060
10417
  // src/sanitizers/prompt-injection.ts
10061
10418
  var SIGNATURES = [
10062
10419
  // --- HIGH severity: clear override / jailbreak attempts ---
@@ -10186,6 +10543,47 @@ var SIGNATURES = [
10186
10543
  severity: "medium",
10187
10544
  description: "ROT13 / Caesar-cipher decode hint"
10188
10545
  },
10546
+ // ── V32: AI agent toolcall injection (improvements.md §1.2) ────────
10547
+ // Modern LLM agents (Claude tool-use, OpenAI function-calling,
10548
+ // ReAct loops) read tool definitions from the system prompt and
10549
+ // JSON-shaped requests from the model. A malicious user can embed
10550
+ // those shapes in their input to make the host think they invoked
10551
+ // a tool, or to trick the model into echoing a synthesized
10552
+ // tool_call that the runtime then executes.
10553
+ //
10554
+ // Narrow patterns — match the literal JSON keys and inline
10555
+ // tool-name shapes. Won't false-positive on plain English text
10556
+ // discussing tools.
10557
+ {
10558
+ rule: "agent-toolcall-marker",
10559
+ pattern: /"(?:tool_call|function_call|call_tool|tool_use|toolUse)"\s*:\s*\{/i,
10560
+ severity: "high",
10561
+ description: 'Injected agent tool-call JSON shape (e.g. {"tool_call":{...}})'
10562
+ },
10563
+ {
10564
+ rule: "agent-tool-name-spoof",
10565
+ pattern: /"name"\s*:\s*"(?:exec|shell|run_command|system|bash|cmd|python|eval|read_file|write_file|delete_file)"/i,
10566
+ severity: "high",
10567
+ description: "Forged tool-name attempting privileged tool invocation"
10568
+ },
10569
+ {
10570
+ rule: "agent-tool-result-marker",
10571
+ pattern: /"(?:tool_result|function_result|tool_output)"\s*:\s*[\{\["]/i,
10572
+ severity: "high",
10573
+ description: "Injected fake tool-result block (trick agent into trusting fabricated output)"
10574
+ },
10575
+ {
10576
+ rule: "ansi-escape-sequence",
10577
+ pattern: /\x1b\[/,
10578
+ severity: "medium",
10579
+ description: "ANSI escape sequence (terminal hijack / output spoofing on CLI agents)"
10580
+ },
10581
+ {
10582
+ rule: "claude-tool-use-tags",
10583
+ pattern: /<\/?\s*(?:tool_use|tool_result|invoke|function_calls?|parameter)\b/i,
10584
+ severity: "high",
10585
+ description: "Claude/OpenAI tool-use XML-style tag forgery"
10586
+ },
10189
10587
  // --- LOW severity: ambiguous but worth flagging in strict mode ---
10190
10588
  {
10191
10589
  rule: "from-now-on",
@@ -10742,6 +11140,7 @@ function createRedisStore(options) {
10742
11140
  exports.ArcisError = ArcisError;
10743
11141
  exports.ArcisValidationError = ValidationError;
10744
11142
  exports.BLOCKED = BLOCKED;
11143
+ exports.CorrelationWindow = CorrelationWindow;
10745
11144
  exports.ERRORS = ERRORS;
10746
11145
  exports.Guards = Guards;
10747
11146
  exports.HEADERS = HEADERS;