@queno/agent-node 0.1.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 (154) hide show
  1. package/README.md +421 -0
  2. package/dist/agent.d.ts +222 -0
  3. package/dist/agent.d.ts.map +1 -0
  4. package/dist/agent.js +591 -0
  5. package/dist/agent.js.map +1 -0
  6. package/dist/api-discovery/discovery-buffer.d.ts +27 -0
  7. package/dist/api-discovery/discovery-buffer.d.ts.map +1 -0
  8. package/dist/api-discovery/discovery-buffer.js +50 -0
  9. package/dist/api-discovery/discovery-buffer.js.map +1 -0
  10. package/dist/api-discovery/endpoint-observer.d.ts +25 -0
  11. package/dist/api-discovery/endpoint-observer.d.ts.map +1 -0
  12. package/dist/api-discovery/endpoint-observer.js +127 -0
  13. package/dist/api-discovery/endpoint-observer.js.map +1 -0
  14. package/dist/api-discovery/route-normalizer.d.ts +15 -0
  15. package/dist/api-discovery/route-normalizer.d.ts.map +1 -0
  16. package/dist/api-discovery/route-normalizer.js +34 -0
  17. package/dist/api-discovery/route-normalizer.js.map +1 -0
  18. package/dist/config.d.ts +100 -0
  19. package/dist/config.d.ts.map +1 -0
  20. package/dist/config.js +101 -0
  21. package/dist/config.js.map +1 -0
  22. package/dist/db-hooks/correlate.d.ts +19 -0
  23. package/dist/db-hooks/correlate.d.ts.map +1 -0
  24. package/dist/db-hooks/correlate.js +45 -0
  25. package/dist/db-hooks/correlate.js.map +1 -0
  26. package/dist/db-hooks/instrument.d.ts +27 -0
  27. package/dist/db-hooks/instrument.d.ts.map +1 -0
  28. package/dist/db-hooks/instrument.js +194 -0
  29. package/dist/db-hooks/instrument.js.map +1 -0
  30. package/dist/detectors/base.d.ts +61 -0
  31. package/dist/detectors/base.d.ts.map +1 -0
  32. package/dist/detectors/base.js +57 -0
  33. package/dist/detectors/base.js.map +1 -0
  34. package/dist/detectors/bola.d.ts +60 -0
  35. package/dist/detectors/bola.d.ts.map +1 -0
  36. package/dist/detectors/bola.js +108 -0
  37. package/dist/detectors/bola.js.map +1 -0
  38. package/dist/detectors/command-injection.d.ts +22 -0
  39. package/dist/detectors/command-injection.d.ts.map +1 -0
  40. package/dist/detectors/command-injection.js +41 -0
  41. package/dist/detectors/command-injection.js.map +1 -0
  42. package/dist/detectors/custom-rule.d.ts +24 -0
  43. package/dist/detectors/custom-rule.d.ts.map +1 -0
  44. package/dist/detectors/custom-rule.js +65 -0
  45. package/dist/detectors/custom-rule.js.map +1 -0
  46. package/dist/detectors/index.d.ts +17 -0
  47. package/dist/detectors/index.d.ts.map +1 -0
  48. package/dist/detectors/index.js +31 -0
  49. package/dist/detectors/index.js.map +1 -0
  50. package/dist/detectors/nosql-injection.d.ts +23 -0
  51. package/dist/detectors/nosql-injection.d.ts.map +1 -0
  52. package/dist/detectors/nosql-injection.js +54 -0
  53. package/dist/detectors/nosql-injection.js.map +1 -0
  54. package/dist/detectors/path-traversal.d.ts +21 -0
  55. package/dist/detectors/path-traversal.d.ts.map +1 -0
  56. package/dist/detectors/path-traversal.js +54 -0
  57. package/dist/detectors/path-traversal.js.map +1 -0
  58. package/dist/detectors/prototype-pollution.d.ts +23 -0
  59. package/dist/detectors/prototype-pollution.d.ts.map +1 -0
  60. package/dist/detectors/prototype-pollution.js +50 -0
  61. package/dist/detectors/prototype-pollution.js.map +1 -0
  62. package/dist/detectors/sql-injection.d.ts +22 -0
  63. package/dist/detectors/sql-injection.d.ts.map +1 -0
  64. package/dist/detectors/sql-injection.js +42 -0
  65. package/dist/detectors/sql-injection.js.map +1 -0
  66. package/dist/detectors/ssrf.d.ts +26 -0
  67. package/dist/detectors/ssrf.d.ts.map +1 -0
  68. package/dist/detectors/ssrf.js +37 -0
  69. package/dist/detectors/ssrf.js.map +1 -0
  70. package/dist/detectors/suspicious-headers.d.ts +25 -0
  71. package/dist/detectors/suspicious-headers.d.ts.map +1 -0
  72. package/dist/detectors/suspicious-headers.js +87 -0
  73. package/dist/detectors/suspicious-headers.js.map +1 -0
  74. package/dist/detectors/template-injection.d.ts +27 -0
  75. package/dist/detectors/template-injection.d.ts.map +1 -0
  76. package/dist/detectors/template-injection.js +35 -0
  77. package/dist/detectors/template-injection.js.map +1 -0
  78. package/dist/detectors/xss.d.ts +22 -0
  79. package/dist/detectors/xss.d.ts.map +1 -0
  80. package/dist/detectors/xss.js +38 -0
  81. package/dist/detectors/xss.js.map +1 -0
  82. package/dist/index.d.ts +28 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +24 -0
  85. package/dist/index.js.map +1 -0
  86. package/dist/integrations/express.d.ts +39 -0
  87. package/dist/integrations/express.d.ts.map +1 -0
  88. package/dist/integrations/express.js +62 -0
  89. package/dist/integrations/express.js.map +1 -0
  90. package/dist/integrations/fastify.d.ts +33 -0
  91. package/dist/integrations/fastify.d.ts.map +1 -0
  92. package/dist/integrations/fastify.js +63 -0
  93. package/dist/integrations/fastify.js.map +1 -0
  94. package/dist/integrations/nestjs.d.ts +40 -0
  95. package/dist/integrations/nestjs.d.ts.map +1 -0
  96. package/dist/integrations/nestjs.js +58 -0
  97. package/dist/integrations/nestjs.js.map +1 -0
  98. package/dist/policy/canonical.d.ts +23 -0
  99. package/dist/policy/canonical.d.ts.map +1 -0
  100. package/dist/policy/canonical.js +40 -0
  101. package/dist/policy/canonical.js.map +1 -0
  102. package/dist/policy/policy-manager.d.ts +43 -0
  103. package/dist/policy/policy-manager.d.ts.map +1 -0
  104. package/dist/policy/policy-manager.js +89 -0
  105. package/dist/policy/policy-manager.js.map +1 -0
  106. package/dist/policy/types.d.ts +70 -0
  107. package/dist/policy/types.d.ts.map +1 -0
  108. package/dist/policy/types.js +2 -0
  109. package/dist/policy/types.js.map +1 -0
  110. package/dist/policy/verify.d.ts +11 -0
  111. package/dist/policy/verify.d.ts.map +1 -0
  112. package/dist/policy/verify.js +61 -0
  113. package/dist/policy/verify.js.map +1 -0
  114. package/dist/redaction/audit-log.d.ts +40 -0
  115. package/dist/redaction/audit-log.d.ts.map +1 -0
  116. package/dist/redaction/audit-log.js +110 -0
  117. package/dist/redaction/audit-log.js.map +1 -0
  118. package/dist/redaction/engine.d.ts +50 -0
  119. package/dist/redaction/engine.d.ts.map +1 -0
  120. package/dist/redaction/engine.js +143 -0
  121. package/dist/redaction/engine.js.map +1 -0
  122. package/dist/redaction/patterns.d.ts +24 -0
  123. package/dist/redaction/patterns.d.ts.map +1 -0
  124. package/dist/redaction/patterns.js +142 -0
  125. package/dist/redaction/patterns.js.map +1 -0
  126. package/dist/runtime-context.d.ts +33 -0
  127. package/dist/runtime-context.d.ts.map +1 -0
  128. package/dist/runtime-context.js +46 -0
  129. package/dist/runtime-context.js.map +1 -0
  130. package/dist/self-protect.d.ts +34 -0
  131. package/dist/self-protect.d.ts.map +1 -0
  132. package/dist/self-protect.js +134 -0
  133. package/dist/self-protect.js.map +1 -0
  134. package/dist/transport/buffer.d.ts +52 -0
  135. package/dist/transport/buffer.d.ts.map +1 -0
  136. package/dist/transport/buffer.js +57 -0
  137. package/dist/transport/buffer.js.map +1 -0
  138. package/dist/transport/client.d.ts +77 -0
  139. package/dist/transport/client.d.ts.map +1 -0
  140. package/dist/transport/client.js +178 -0
  141. package/dist/transport/client.js.map +1 -0
  142. package/dist/transport/heartbeat.d.ts +86 -0
  143. package/dist/transport/heartbeat.d.ts.map +1 -0
  144. package/dist/transport/heartbeat.js +110 -0
  145. package/dist/transport/heartbeat.js.map +1 -0
  146. package/dist/transport/secure-request.d.ts +30 -0
  147. package/dist/transport/secure-request.d.ts.map +1 -0
  148. package/dist/transport/secure-request.js +95 -0
  149. package/dist/transport/secure-request.js.map +1 -0
  150. package/dist/types.d.ts +311 -0
  151. package/dist/types.d.ts.map +1 -0
  152. package/dist/types.js +12 -0
  153. package/dist/types.js.map +1 -0
  154. package/package.json +60 -0
@@ -0,0 +1,65 @@
1
+ import { flattenValues } from "./base.js";
2
+ export class CustomRuleDetector {
3
+ name = "custom-rule";
4
+ rules;
5
+ constructor(specs) {
6
+ this.rules = [];
7
+ for (const spec of specs) {
8
+ if (spec.enabled === false)
9
+ continue;
10
+ if (!spec.pattern)
11
+ continue;
12
+ try {
13
+ this.rules.push({ spec, regex: new RegExp(spec.pattern, "i") });
14
+ }
15
+ catch {
16
+ // Skip invalid regex - never throw at construction time.
17
+ }
18
+ }
19
+ }
20
+ /** Number of active compiled rules (useful for diagnostics/tests). */
21
+ get size() {
22
+ return this.rules.length;
23
+ }
24
+ valuesFor(req, target) {
25
+ switch (target) {
26
+ case "path":
27
+ return [req.path];
28
+ case "query":
29
+ return flattenValues(req.query);
30
+ case "body":
31
+ return flattenValues(req.body);
32
+ case "headers":
33
+ return flattenValues(req.headers);
34
+ case "any":
35
+ default:
36
+ return [
37
+ req.path,
38
+ ...flattenValues(req.query),
39
+ ...flattenValues(req.body),
40
+ ...flattenValues(req.headers),
41
+ ];
42
+ }
43
+ }
44
+ detect(req) {
45
+ for (const { spec, regex } of this.rules) {
46
+ const values = this.valuesFor(req, spec.target ?? "any");
47
+ for (const val of values) {
48
+ if (typeof val !== "string")
49
+ continue;
50
+ if (regex.test(val)) {
51
+ return {
52
+ detectorName: spec.id,
53
+ eventType: spec.eventType ?? "custom_rule",
54
+ severity: spec.severity ?? "medium",
55
+ description: spec.description ?? spec.name ?? `Custom rule ${spec.id} matched`,
56
+ matchedValue: val.slice(0, 200),
57
+ location: spec.target ?? "any",
58
+ };
59
+ }
60
+ }
61
+ }
62
+ return null;
63
+ }
64
+ }
65
+ //# sourceMappingURL=custom-rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-rule.js","sourceRoot":"","sources":["../../src/detectors/custom-rule.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAS1C,MAAM,OAAO,kBAAkB;IACpB,IAAI,GAAG,aAAa,CAAC;IACb,KAAK,CAAiB;IAEvC,YAAY,KAAuB;QACjC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK;gBAAE,SAAS;YACrC,IAAI,CAAC,IAAI,CAAC,OAAO;gBAAE,SAAS;YAC5B,IAAI,CAAC;gBACH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAClE,CAAC;YAAC,MAAM,CAAC;gBACP,yDAAyD;YAC3D,CAAC;QACH,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;IAEO,SAAS,CAAC,GAAsB,EAAE,MAAgC;QACxE,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,MAAM;gBACT,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACpB,KAAK,OAAO;gBACV,OAAO,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAClC,KAAK,MAAM;gBACT,OAAO,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACjC,KAAK,SAAS;gBACZ,OAAO,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACpC,KAAK,KAAK,CAAC;YACX;gBACE,OAAO;oBACL,GAAG,CAAC,IAAI;oBACR,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;oBAC3B,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;oBAC1B,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC;iBAC9B,CAAC;QACN,CAAC;IACH,CAAC;IAED,MAAM,CAAC,GAAsB;QAC3B,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACzC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC;YACzD,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;gBACzB,IAAI,OAAO,GAAG,KAAK,QAAQ;oBAAE,SAAS;gBACtC,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACpB,OAAO;wBACL,YAAY,EAAE,IAAI,CAAC,EAAE;wBACrB,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,aAAa;wBAC1C,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,QAAQ;wBACnC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,IAAI,eAAe,IAAI,CAAC,EAAE,UAAU;wBAC9E,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;wBAC/B,QAAQ,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;qBAC/B,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Default detector set bundled with the agent.
3
+ *
4
+ * Order matters: {@link RaspAgent.inspect} returns on the first non-null
5
+ * detection, so detectors with higher signal/lower false-positive rates and
6
+ * higher severity come first.
7
+ */
8
+ import type { Detector } from "./base.js";
9
+ export { type Detector } from "./base.js";
10
+ /**
11
+ * Build a fresh array of the bundled detectors.
12
+ *
13
+ * Each call returns brand-new detector instances - important because a few
14
+ * detectors (notably {@link BolaDetector}) carry per-IP state.
15
+ */
16
+ export declare function createDefaultDetectors(): Detector[];
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/detectors/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAY1C,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,sBAAsB,IAAI,QAAQ,EAAE,CAanD"}
@@ -0,0 +1,31 @@
1
+ import { SqlInjectionDetector } from "./sql-injection.js";
2
+ import { XssDetector } from "./xss.js";
3
+ import { CommandInjectionDetector } from "./command-injection.js";
4
+ import { PathTraversalDetector } from "./path-traversal.js";
5
+ import { NoSqlInjectionDetector } from "./nosql-injection.js";
6
+ import { SsrfDetector } from "./ssrf.js";
7
+ import { PrototypePollutionDetector } from "./prototype-pollution.js";
8
+ import { TemplateInjectionDetector } from "./template-injection.js";
9
+ import { SuspiciousHeadersDetector } from "./suspicious-headers.js";
10
+ import { BolaDetector } from "./bola.js";
11
+ /**
12
+ * Build a fresh array of the bundled detectors.
13
+ *
14
+ * Each call returns brand-new detector instances - important because a few
15
+ * detectors (notably {@link BolaDetector}) carry per-IP state.
16
+ */
17
+ export function createDefaultDetectors() {
18
+ return [
19
+ new SqlInjectionDetector(),
20
+ new XssDetector(),
21
+ new CommandInjectionDetector(),
22
+ new PathTraversalDetector(),
23
+ new NoSqlInjectionDetector(),
24
+ new SsrfDetector(),
25
+ new PrototypePollutionDetector(),
26
+ new TemplateInjectionDetector(),
27
+ new SuspiciousHeadersDetector(),
28
+ new BolaDetector(),
29
+ ];
30
+ }
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/detectors/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAIzC;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,IAAI,oBAAoB,EAAE;QAC1B,IAAI,WAAW,EAAE;QACjB,IAAI,wBAAwB,EAAE;QAC9B,IAAI,qBAAqB,EAAE;QAC3B,IAAI,sBAAsB,EAAE;QAC5B,IAAI,YAAY,EAAE;QAClB,IAAI,0BAA0B,EAAE;QAChC,IAAI,yBAAyB,EAAE;QAC/B,IAAI,yBAAyB,EAAE;QAC/B,IAAI,YAAY,EAAE;KACnB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * NoSQL (primarily MongoDB) injection signature detector.
3
+ *
4
+ * Two complementary strategies:
5
+ *
6
+ * 1. **Value scan** - string values are checked for serialised MongoDB
7
+ * operator forms (`$where:`, `{ $gt: ... }`, `mapReduce(...)`). Catches
8
+ * payloads injected through query strings or JSON bodies that the
9
+ * application later passes through unsafe deserialisation.
10
+ *
11
+ * 2. **Key scan** - any leaf object key matching `^$[a-z]+$` is flagged.
12
+ * This is the classic `{ password: { $gt: "" } }` attack where the
13
+ * operator is smuggled in as a sub-object instead of a scalar.
14
+ *
15
+ * Severity: `high`.
16
+ */
17
+ import type { Detector } from "./base.js";
18
+ import type { DetectionResult, NormalizedRequest } from "../types.js";
19
+ export declare class NoSqlInjectionDetector implements Detector {
20
+ readonly name = "nosql-injection";
21
+ detect(req: NormalizedRequest): DetectionResult | null;
22
+ }
23
+ //# sourceMappingURL=nosql-injection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nosql-injection.d.ts","sourceRoot":"","sources":["../../src/detectors/nosql-injection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAqBtE,qBAAa,sBAAuB,YAAW,QAAQ;IACrD,QAAQ,CAAC,IAAI,qBAAqB;IAElC,MAAM,CAAC,GAAG,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI;CAkCvD"}
@@ -0,0 +1,54 @@
1
+ import { flattenEntries, flattenValues } from "./base.js";
2
+ /** MongoDB operator patterns expected to appear in string values. */
3
+ const NOSQL_STRING_PATTERNS = [
4
+ /\$where\s*:/i,
5
+ /\$regex\s*:/i,
6
+ /\{\s*\$gt\s*:/i,
7
+ /\{\s*\$lt\s*:/i,
8
+ /\{\s*\$ne\s*:/i,
9
+ /\{\s*\$in\s*:/i,
10
+ /\{\s*\$nin\s*:/i,
11
+ /\{\s*\$or\s*:/i,
12
+ /\{\s*\$and\s*:/i,
13
+ /\{\s*\$not\s*:/i,
14
+ /\{\s*\$exists\s*:/i,
15
+ /mapReduce\s*\(/i,
16
+ ];
17
+ /** MongoDB operators showing up as object keys (e.g. `{ "$gt": "" }`). */
18
+ const NOSQL_KEY_PATTERN = /^\$[a-z]+$/i;
19
+ export class NoSqlInjectionDetector {
20
+ name = "nosql-injection";
21
+ detect(req) {
22
+ const values = [...flattenValues(req.query), ...flattenValues(req.body)];
23
+ for (const val of values) {
24
+ for (const pattern of NOSQL_STRING_PATTERNS) {
25
+ if (pattern.test(val)) {
26
+ return {
27
+ detectorName: this.name,
28
+ eventType: "nosql_injection",
29
+ severity: "high",
30
+ description: "NoSQL injection pattern detected in value",
31
+ matchedValue: val.slice(0, 200),
32
+ location: "query/body",
33
+ };
34
+ }
35
+ }
36
+ }
37
+ const entries = [...flattenEntries(req.query), ...flattenEntries(req.body)];
38
+ for (const [key] of entries) {
39
+ const leaf = key.split(".").pop() ?? "";
40
+ if (NOSQL_KEY_PATTERN.test(leaf)) {
41
+ return {
42
+ detectorName: this.name,
43
+ eventType: "nosql_injection",
44
+ severity: "high",
45
+ description: "NoSQL operator key detected in request object",
46
+ matchedValue: key,
47
+ location: "query/body",
48
+ };
49
+ }
50
+ }
51
+ return null;
52
+ }
53
+ }
54
+ //# sourceMappingURL=nosql-injection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nosql-injection.js","sourceRoot":"","sources":["../../src/detectors/nosql-injection.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1D,qEAAqE;AACrE,MAAM,qBAAqB,GAAG;IAC5B,cAAc;IACd,cAAc;IACd,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,iBAAiB;IACjB,gBAAgB;IAChB,iBAAiB;IACjB,iBAAiB;IACjB,oBAAoB;IACpB,iBAAiB;CAClB,CAAC;AAEF,0EAA0E;AAC1E,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAExC,MAAM,OAAO,sBAAsB;IACxB,IAAI,GAAG,iBAAiB,CAAC;IAElC,MAAM,CAAC,GAAsB;QAC3B,MAAM,MAAM,GAAG,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QACzE,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,KAAK,MAAM,OAAO,IAAI,qBAAqB,EAAE,CAAC;gBAC5C,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtB,OAAO;wBACL,YAAY,EAAE,IAAI,CAAC,IAAI;wBACvB,SAAS,EAAE,iBAAiB;wBAC5B,QAAQ,EAAE,MAAM;wBAChB,WAAW,EAAE,2CAA2C;wBACxD,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;wBAC/B,QAAQ,EAAE,YAAY;qBACvB,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5E,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YACxC,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjC,OAAO;oBACL,YAAY,EAAE,IAAI,CAAC,IAAI;oBACvB,SAAS,EAAE,iBAAiB;oBAC5B,QAAQ,EAAE,MAAM;oBAChB,WAAW,EAAE,+CAA+C;oBAC5D,YAAY,EAAE,GAAG;oBACjB,QAAQ,EAAE,YAAY;iBACvB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Path traversal signature detector.
3
+ *
4
+ * Scans `query`, `body` and `path` for `../` and `..\` sequences, their
5
+ * URL-encoded (`%2e%2e%2f`) and double-encoded (`%252e%252e`) variants,
6
+ * NUL-byte truncation, and references to canonical loot files
7
+ * (`/etc/passwd`, `/etc/shadow`, `win.ini`, `boot.ini`).
8
+ *
9
+ * Severity: `high`.
10
+ *
11
+ * Implementation note: each value is also tried after a single pass of
12
+ * `decodeURIComponent` to catch the simplest encoding bypasses without
13
+ * paying for a full normalisation pipeline.
14
+ */
15
+ import type { Detector } from "./base.js";
16
+ import type { DetectionResult, NormalizedRequest } from "../types.js";
17
+ export declare class PathTraversalDetector implements Detector {
18
+ readonly name = "path-traversal";
19
+ detect(req: NormalizedRequest): DetectionResult | null;
20
+ }
21
+ //# sourceMappingURL=path-traversal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-traversal.d.ts","sourceRoot":"","sources":["../../src/detectors/path-traversal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAiBtE,qBAAa,qBAAsB,YAAW,QAAQ;IACpD,QAAQ,CAAC,IAAI,oBAAoB;IAEjC,MAAM,CAAC,GAAG,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI;CAwBvD"}
@@ -0,0 +1,54 @@
1
+ import { flattenValues } from "./base.js";
2
+ const PATH_PATTERNS = [
3
+ /\.\.[/\\]/,
4
+ /[/\\]\.\./,
5
+ /%2e%2e[%2f%5c]/i,
6
+ /%252e%252e/i,
7
+ /\.\.%2f/i,
8
+ /\.\.%5c/i,
9
+ /\x00/,
10
+ /\/etc\/passwd/i,
11
+ /\/etc\/shadow/i,
12
+ /\/windows\/win\.ini/i,
13
+ /\/winnt\/win\.ini/i,
14
+ /boot\.ini/i,
15
+ ];
16
+ export class PathTraversalDetector {
17
+ name = "path-traversal";
18
+ detect(req) {
19
+ const values = [
20
+ ...flattenValues(req.query),
21
+ ...flattenValues(req.body),
22
+ req.path,
23
+ ];
24
+ for (const val of values) {
25
+ const decoded = tryDecode(val);
26
+ for (const pattern of PATH_PATTERNS) {
27
+ if (pattern.test(val) || pattern.test(decoded)) {
28
+ return {
29
+ detectorName: this.name,
30
+ eventType: "path_traversal",
31
+ severity: "high",
32
+ description: "Path traversal pattern detected",
33
+ matchedValue: val.slice(0, 200),
34
+ location: "query/body/path",
35
+ };
36
+ }
37
+ }
38
+ }
39
+ return null;
40
+ }
41
+ }
42
+ /**
43
+ * Best-effort `decodeURIComponent`. Falls back to the original string when
44
+ * the input contains malformed percent-escapes.
45
+ */
46
+ function tryDecode(val) {
47
+ try {
48
+ return decodeURIComponent(val);
49
+ }
50
+ catch {
51
+ return val;
52
+ }
53
+ }
54
+ //# sourceMappingURL=path-traversal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-traversal.js","sourceRoot":"","sources":["../../src/detectors/path-traversal.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,aAAa,GAAG;IACpB,WAAW;IACX,WAAW;IACX,iBAAiB;IACjB,aAAa;IACb,UAAU;IACV,UAAU;IACV,MAAM;IACN,gBAAgB;IAChB,gBAAgB;IAChB,sBAAsB;IACtB,oBAAoB;IACpB,YAAY;CACb,CAAC;AAEF,MAAM,OAAO,qBAAqB;IACvB,IAAI,GAAG,gBAAgB,CAAC;IAEjC,MAAM,CAAC,GAAsB;QAC3B,MAAM,MAAM,GAAG;YACb,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;YAC3B,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;YAC1B,GAAG,CAAC,IAAI;SACT,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;YAC/B,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;gBACpC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC/C,OAAO;wBACL,YAAY,EAAE,IAAI,CAAC,IAAI;wBACvB,SAAS,EAAE,gBAAgB;wBAC3B,QAAQ,EAAE,MAAM;wBAChB,WAAW,EAAE,iCAAiC;wBAC9C,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;wBAC/B,QAAQ,EAAE,iBAAiB;qBAC5B,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED;;;GAGG;AACH,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Prototype pollution signature detector.
3
+ *
4
+ * Two strategies:
5
+ *
6
+ * 1. **Key scan** - flags any nested key equal to `__proto__`, `constructor`
7
+ * or `prototype`, plus dotted forms like `a.__proto__` and
8
+ * `a.constructor.prototype` used by some merge utilities.
9
+ *
10
+ * 2. **Value scan** - flags string values that look like a JSON-encoded
11
+ * pollution payload (e.g. `"__proto__": { ... }`), which is what attackers
12
+ * send when the application later parses the field with `JSON.parse`.
13
+ *
14
+ * Severity: `critical` - prototype pollution typically chains into RCE,
15
+ * authentication bypass, or arbitrary file read.
16
+ */
17
+ import type { Detector } from "./base.js";
18
+ import type { DetectionResult, NormalizedRequest } from "../types.js";
19
+ export declare class PrototypePollutionDetector implements Detector {
20
+ readonly name = "prototype-pollution";
21
+ detect(req: NormalizedRequest): DetectionResult | null;
22
+ }
23
+ //# sourceMappingURL=prototype-pollution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prototype-pollution.d.ts","sourceRoot":"","sources":["../../src/detectors/prototype-pollution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAgBtE,qBAAa,0BAA2B,YAAW,QAAQ;IACzD,QAAQ,CAAC,IAAI,yBAAyB;IAEtC,MAAM,CAAC,GAAG,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI;CAmCvD"}
@@ -0,0 +1,50 @@
1
+ import { flattenEntries, flattenValues } from "./base.js";
2
+ const POLLUTION_KEY_PATTERNS = [
3
+ /^__proto__$/,
4
+ /^constructor$/,
5
+ /^prototype$/,
6
+ /\.__proto__/,
7
+ /\.constructor\.prototype/,
8
+ ];
9
+ const POLLUTION_VALUE_PATTERNS = [
10
+ /"__proto__"\s*:/,
11
+ /"constructor"\s*:\s*\{/,
12
+ /"prototype"\s*:\s*\{/,
13
+ ];
14
+ export class PrototypePollutionDetector {
15
+ name = "prototype-pollution";
16
+ detect(req) {
17
+ const entries = [...flattenEntries(req.query), ...flattenEntries(req.body)];
18
+ for (const [key] of entries) {
19
+ for (const pattern of POLLUTION_KEY_PATTERNS) {
20
+ if (pattern.test(key)) {
21
+ return {
22
+ detectorName: this.name,
23
+ eventType: "prototype_pollution",
24
+ severity: "critical",
25
+ description: "Prototype pollution key detected in request",
26
+ matchedValue: key,
27
+ location: "query/body key",
28
+ };
29
+ }
30
+ }
31
+ }
32
+ const values = [...flattenValues(req.query), ...flattenValues(req.body)];
33
+ for (const val of values) {
34
+ for (const pattern of POLLUTION_VALUE_PATTERNS) {
35
+ if (pattern.test(val)) {
36
+ return {
37
+ detectorName: this.name,
38
+ eventType: "prototype_pollution",
39
+ severity: "critical",
40
+ description: "Prototype pollution pattern detected in serialised value",
41
+ matchedValue: val.slice(0, 200),
42
+ location: "query/body value",
43
+ };
44
+ }
45
+ }
46
+ }
47
+ return null;
48
+ }
49
+ }
50
+ //# sourceMappingURL=prototype-pollution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prototype-pollution.js","sourceRoot":"","sources":["../../src/detectors/prototype-pollution.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1D,MAAM,sBAAsB,GAAG;IAC7B,aAAa;IACb,eAAe;IACf,aAAa;IACb,aAAa;IACb,0BAA0B;CAC3B,CAAC;AAEF,MAAM,wBAAwB,GAAG;IAC/B,iBAAiB;IACjB,wBAAwB;IACxB,sBAAsB;CACvB,CAAC;AAEF,MAAM,OAAO,0BAA0B;IAC5B,IAAI,GAAG,qBAAqB,CAAC;IAEtC,MAAM,CAAC,GAAsB;QAC3B,MAAM,OAAO,GAAG,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5E,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,OAAO,EAAE,CAAC;YAC5B,KAAK,MAAM,OAAO,IAAI,sBAAsB,EAAE,CAAC;gBAC7C,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtB,OAAO;wBACL,YAAY,EAAE,IAAI,CAAC,IAAI;wBACvB,SAAS,EAAE,qBAAqB;wBAChC,QAAQ,EAAE,UAAU;wBACpB,WAAW,EAAE,6CAA6C;wBAC1D,YAAY,EAAE,GAAG;wBACjB,QAAQ,EAAE,gBAAgB;qBAC3B,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QACzE,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,KAAK,MAAM,OAAO,IAAI,wBAAwB,EAAE,CAAC;gBAC/C,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtB,OAAO;wBACL,YAAY,EAAE,IAAI,CAAC,IAAI;wBACvB,SAAS,EAAE,qBAAqB;wBAChC,QAAQ,EAAE,UAAU;wBACpB,WAAW,EAAE,0DAA0D;wBACvE,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;wBAC/B,QAAQ,EAAE,kBAAkB;qBAC7B,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * SQL injection signature detector.
3
+ *
4
+ * Inspects the request `query`, `body` and `path` for textbook SQLi patterns:
5
+ * UNION SELECT, tautology probes (`' OR 1=1`), inline comments, stacked
6
+ * statements with destructive verbs, blind-injection sleep functions and
7
+ * SQL Server metadata views.
8
+ *
9
+ * Severity: `critical` - SQLi typically yields direct data exfiltration.
10
+ *
11
+ * Known limits: pattern-based; an attacker who heavily obfuscates the
12
+ * payload (case mixing, comments between keywords) may evade some signatures.
13
+ * Headers are intentionally **not** scanned to keep cost down - they're
14
+ * covered by other detectors.
15
+ */
16
+ import type { Detector } from "./base.js";
17
+ import type { DetectionResult, NormalizedRequest } from "../types.js";
18
+ export declare class SqlInjectionDetector implements Detector {
19
+ readonly name = "sql-injection";
20
+ detect(req: NormalizedRequest): DetectionResult | null;
21
+ }
22
+ //# sourceMappingURL=sql-injection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-injection.d.ts","sourceRoot":"","sources":["../../src/detectors/sql-injection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAG,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAkBtE,qBAAa,oBAAqB,YAAW,QAAQ;IACnD,QAAQ,CAAC,IAAI,mBAAmB;IAEhC,MAAM,CAAC,GAAG,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI;CAuBvD"}
@@ -0,0 +1,42 @@
1
+ import { flattenValues } from "./base.js";
2
+ const SQL_PATTERNS = [
3
+ /(\b)(union\s+select|union\s+all\s+select)/i,
4
+ /'\s*(or|and)\s+['"]?\d/i,
5
+ /'\s*(or|and)\s+\w+\s*=\s*\w*/i,
6
+ /--\s*$/m,
7
+ /;\s*(drop|delete|insert|update|truncate|alter|exec|execute)\b/i,
8
+ /\bxp_cmdshell\b/i,
9
+ /\bWAITFOR\s+DELAY\b/i,
10
+ /\bSLEEP\s*\(\s*\d/i,
11
+ /\bBENCHMARK\s*\(/i,
12
+ /\/\*.*?\*\//s,
13
+ /\bINFORMATION_SCHEMA\b/i,
14
+ /\bSYSOBJECTS\b/i,
15
+ /\bCHAR\s*\(\s*\d+\s*\)/i,
16
+ ];
17
+ export class SqlInjectionDetector {
18
+ name = "sql-injection";
19
+ detect(req) {
20
+ const values = [
21
+ ...flattenValues(req.query),
22
+ ...flattenValues(req.body),
23
+ req.path,
24
+ ];
25
+ for (const val of values) {
26
+ for (const pattern of SQL_PATTERNS) {
27
+ if (pattern.test(val)) {
28
+ return {
29
+ detectorName: this.name,
30
+ eventType: "sql_injection",
31
+ severity: "critical",
32
+ description: "SQL injection pattern detected",
33
+ matchedValue: val.slice(0, 200),
34
+ location: "query/body/path",
35
+ };
36
+ }
37
+ }
38
+ }
39
+ return null;
40
+ }
41
+ }
42
+ //# sourceMappingURL=sql-injection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-injection.js","sourceRoot":"","sources":["../../src/detectors/sql-injection.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,YAAY,GAAG;IACnB,4CAA4C;IAC5C,yBAAyB;IACzB,+BAA+B;IAC/B,SAAS;IACT,gEAAgE;IAChE,kBAAkB;IAClB,sBAAsB;IACtB,oBAAoB;IACpB,mBAAmB;IACnB,cAAc;IACd,yBAAyB;IACzB,iBAAiB;IACjB,yBAAyB;CAC1B,CAAC;AAEF,MAAM,OAAO,oBAAoB;IACtB,IAAI,GAAG,eAAe,CAAC;IAEhC,MAAM,CAAC,GAAsB;QAC3B,MAAM,MAAM,GAAG;YACb,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;YAC3B,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;YAC1B,GAAG,CAAC,IAAI;SACT,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;gBACnC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtB,OAAO;wBACL,YAAY,EAAE,IAAI,CAAC,IAAI;wBACvB,SAAS,EAAE,eAAe;wBAC1B,QAAQ,EAAE,UAAU;wBACpB,WAAW,EAAE,gCAAgC;wBAC7C,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;wBAC/B,QAAQ,EAAE,iBAAiB;qBAC5B,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Server-Side Request Forgery (SSRF) signature detector.
3
+ *
4
+ * Flags request parameters carrying URLs that target destinations a
5
+ * server-side fetch should rarely visit:
6
+ *
7
+ * - Loopback addresses (`localhost`, `127.0.0.0/8`, `0.0.0.0`, `[::1]`).
8
+ * - RFC 1918 private ranges (`10/8`, `172.16/12`, `192.168/16`).
9
+ * - Cloud metadata endpoints (`169.254.169.254` for AWS/Azure,
10
+ * `metadata.google.internal` for GCP).
11
+ * - Dangerous protocols (`file://`, `gopher://`, `dict://`, `ftp://`).
12
+ *
13
+ * Severity: `high`.
14
+ *
15
+ * Known limits: matching is purely lexical. DNS-rebinding payloads
16
+ * (`internal.attacker.com` resolving to `127.0.0.1`) and Unicode
17
+ * homoglyphs in hostnames are not caught here - they need runtime DNS
18
+ * inspection which is out of scope.
19
+ */
20
+ import type { Detector } from "./base.js";
21
+ import type { DetectionResult, NormalizedRequest } from "../types.js";
22
+ export declare class SsrfDetector implements Detector {
23
+ readonly name = "ssrf";
24
+ detect(req: NormalizedRequest): DetectionResult | null;
25
+ }
26
+ //# sourceMappingURL=ssrf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrf.d.ts","sourceRoot":"","sources":["../../src/detectors/ssrf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAiBtE,qBAAa,YAAa,YAAW,QAAQ;IAC3C,QAAQ,CAAC,IAAI,UAAU;IAEvB,MAAM,CAAC,GAAG,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI;CAmBvD"}
@@ -0,0 +1,37 @@
1
+ import { flattenValues } from "./base.js";
2
+ const SSRF_PATTERNS = [
3
+ /https?:\/\/localhost/i,
4
+ /https?:\/\/127\.\d+\.\d+\.\d+/,
5
+ /https?:\/\/0\.0\.0\.0/,
6
+ /https?:\/\/\[::1\]/,
7
+ /https?:\/\/10\.\d+\.\d+\.\d+/,
8
+ /https?:\/\/172\.(1[6-9]|2\d|3[01])\.\d+\.\d+/,
9
+ /https?:\/\/192\.168\.\d+\.\d+/,
10
+ /https?:\/\/169\.254\.169\.254/,
11
+ /https?:\/\/metadata\.google\.internal/i,
12
+ /https?:\/\/169\.254\.169\.254\/metadata/i,
13
+ /^file:\/\//i,
14
+ /^(gopher|dict|ftp):\/\//i,
15
+ ];
16
+ export class SsrfDetector {
17
+ name = "ssrf";
18
+ detect(req) {
19
+ const values = [...flattenValues(req.query), ...flattenValues(req.body)];
20
+ for (const val of values) {
21
+ for (const pattern of SSRF_PATTERNS) {
22
+ if (pattern.test(val)) {
23
+ return {
24
+ detectorName: this.name,
25
+ eventType: "ssrf",
26
+ severity: "high",
27
+ description: "SSRF - request targets an internal or metadata endpoint",
28
+ matchedValue: val.slice(0, 200),
29
+ location: "query/body",
30
+ };
31
+ }
32
+ }
33
+ }
34
+ return null;
35
+ }
36
+ }
37
+ //# sourceMappingURL=ssrf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrf.js","sourceRoot":"","sources":["../../src/detectors/ssrf.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,aAAa,GAAG;IACpB,uBAAuB;IACvB,+BAA+B;IAC/B,uBAAuB;IACvB,oBAAoB;IACpB,8BAA8B;IAC9B,8CAA8C;IAC9C,+BAA+B;IAC/B,+BAA+B;IAC/B,wCAAwC;IACxC,0CAA0C;IAC1C,aAAa;IACb,0BAA0B;CAC3B,CAAC;AAEF,MAAM,OAAO,YAAY;IACd,IAAI,GAAG,MAAM,CAAC;IAEvB,MAAM,CAAC,GAAsB;QAC3B,MAAM,MAAM,GAAG,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAEzE,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;gBACpC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtB,OAAO;wBACL,YAAY,EAAE,IAAI,CAAC,IAAI;wBACvB,SAAS,EAAE,MAAM;wBACjB,QAAQ,EAAE,MAAM;wBAChB,WAAW,EAAE,yDAAyD;wBACtE,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;wBAC/B,QAAQ,EAAE,YAAY;qBACvB,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Suspicious HTTP-header detector.
3
+ *
4
+ * Catches a handful of abuse patterns that don't fit elsewhere:
5
+ *
6
+ * - Header floods (more than {@link MAX_HEADERS_COUNT} headers).
7
+ * - Oversized header values (> {@link MAX_HEADER_VALUE_LENGTH} bytes).
8
+ * - `Host` headers containing characters outside the legal hostname set
9
+ * (Host-header injection probes).
10
+ * - `X-Forwarded-For` values smuggling RFC1918 addresses (source-IP
11
+ * spoofing toward downstream services that trust the header).
12
+ * - CRLF (`\r` / `\n`) anywhere in a header value (HTTP response
13
+ * splitting / log injection).
14
+ *
15
+ * Severity is `medium` for the structural anomalies (count, size,
16
+ * `X-Forwarded-For` spoof, host-header injection) and `high` for newline
17
+ * injection, which is more directly weaponisable.
18
+ */
19
+ import type { Detector } from "./base.js";
20
+ import type { DetectionResult, NormalizedRequest } from "../types.js";
21
+ export declare class SuspiciousHeadersDetector implements Detector {
22
+ readonly name = "suspicious-headers";
23
+ detect(req: NormalizedRequest): DetectionResult | null;
24
+ }
25
+ //# sourceMappingURL=suspicious-headers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suspicious-headers.d.ts","sourceRoot":"","sources":["../../src/detectors/suspicious-headers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAatE,qBAAa,yBAA0B,YAAW,QAAQ;IACxD,QAAQ,CAAC,IAAI,wBAAwB;IAErC,MAAM,CAAC,GAAG,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI;CAoEvD"}