mcp-recon 0.2.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 (95) hide show
  1. package/LICENSE +19 -0
  2. package/README.md +271 -0
  3. package/dist/bin/recon.d.ts +18 -0
  4. package/dist/bin/recon.d.ts.map +1 -0
  5. package/dist/bin/recon.js +361 -0
  6. package/dist/bin/recon.js.map +1 -0
  7. package/dist/caveats/index.d.ts +46 -0
  8. package/dist/caveats/index.d.ts.map +1 -0
  9. package/dist/caveats/index.js +186 -0
  10. package/dist/caveats/index.js.map +1 -0
  11. package/dist/caveats/render.d.ts +25 -0
  12. package/dist/caveats/render.d.ts.map +1 -0
  13. package/dist/caveats/render.js +100 -0
  14. package/dist/caveats/render.js.map +1 -0
  15. package/dist/caveats/types.d.ts +94 -0
  16. package/dist/caveats/types.d.ts.map +1 -0
  17. package/dist/caveats/types.js +17 -0
  18. package/dist/caveats/types.js.map +1 -0
  19. package/dist/classify/caveat.d.ts +29 -0
  20. package/dist/classify/caveat.d.ts.map +1 -0
  21. package/dist/classify/caveat.js +103 -0
  22. package/dist/classify/caveat.js.map +1 -0
  23. package/dist/classify/index.d.ts +21 -0
  24. package/dist/classify/index.d.ts.map +1 -0
  25. package/dist/classify/index.js +186 -0
  26. package/dist/classify/index.js.map +1 -0
  27. package/dist/classify/rules.d.ts +62 -0
  28. package/dist/classify/rules.d.ts.map +1 -0
  29. package/dist/classify/rules.js +219 -0
  30. package/dist/classify/rules.js.map +1 -0
  31. package/dist/classify/types.d.ts +45 -0
  32. package/dist/classify/types.d.ts.map +1 -0
  33. package/dist/classify/types.js +9 -0
  34. package/dist/classify/types.js.map +1 -0
  35. package/dist/enumerate.d.ts +79 -0
  36. package/dist/enumerate.d.ts.map +1 -0
  37. package/dist/enumerate.js +62 -0
  38. package/dist/enumerate.js.map +1 -0
  39. package/dist/fuzz/axes/boundary.d.ts +17 -0
  40. package/dist/fuzz/axes/boundary.d.ts.map +1 -0
  41. package/dist/fuzz/axes/boundary.js +143 -0
  42. package/dist/fuzz/axes/boundary.js.map +1 -0
  43. package/dist/fuzz/axes/encoding.d.ts +17 -0
  44. package/dist/fuzz/axes/encoding.d.ts.map +1 -0
  45. package/dist/fuzz/axes/encoding.js +59 -0
  46. package/dist/fuzz/axes/encoding.js.map +1 -0
  47. package/dist/fuzz/axes/path-traversal.d.ts +17 -0
  48. package/dist/fuzz/axes/path-traversal.d.ts.map +1 -0
  49. package/dist/fuzz/axes/path-traversal.js +56 -0
  50. package/dist/fuzz/axes/path-traversal.js.map +1 -0
  51. package/dist/fuzz/axes/schema-violation.d.ts +18 -0
  52. package/dist/fuzz/axes/schema-violation.d.ts.map +1 -0
  53. package/dist/fuzz/axes/schema-violation.js +74 -0
  54. package/dist/fuzz/axes/schema-violation.js.map +1 -0
  55. package/dist/fuzz/axes/type-confusion.d.ts +17 -0
  56. package/dist/fuzz/axes/type-confusion.d.ts.map +1 -0
  57. package/dist/fuzz/axes/type-confusion.js +67 -0
  58. package/dist/fuzz/axes/type-confusion.js.map +1 -0
  59. package/dist/fuzz/axes/url-hostility.d.ts +17 -0
  60. package/dist/fuzz/axes/url-hostility.d.ts.map +1 -0
  61. package/dist/fuzz/axes/url-hostility.js +61 -0
  62. package/dist/fuzz/axes/url-hostility.js.map +1 -0
  63. package/dist/fuzz/index.d.ts +41 -0
  64. package/dist/fuzz/index.d.ts.map +1 -0
  65. package/dist/fuzz/index.js +147 -0
  66. package/dist/fuzz/index.js.map +1 -0
  67. package/dist/fuzz/prng.d.ts +26 -0
  68. package/dist/fuzz/prng.d.ts.map +1 -0
  69. package/dist/fuzz/prng.js +52 -0
  70. package/dist/fuzz/prng.js.map +1 -0
  71. package/dist/fuzz/schema.d.ts +46 -0
  72. package/dist/fuzz/schema.d.ts.map +1 -0
  73. package/dist/fuzz/schema.js +84 -0
  74. package/dist/fuzz/schema.js.map +1 -0
  75. package/dist/fuzz/types.d.ts +53 -0
  76. package/dist/fuzz/types.d.ts.map +1 -0
  77. package/dist/fuzz/types.js +11 -0
  78. package/dist/fuzz/types.js.map +1 -0
  79. package/dist/index.d.ts +25 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +25 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/report/index.d.ts +25 -0
  84. package/dist/report/index.d.ts.map +1 -0
  85. package/dist/report/index.js +133 -0
  86. package/dist/report/index.js.map +1 -0
  87. package/dist/scan/index.d.ts +52 -0
  88. package/dist/scan/index.d.ts.map +1 -0
  89. package/dist/scan/index.js +81 -0
  90. package/dist/scan/index.js.map +1 -0
  91. package/dist/transport.d.ts +43 -0
  92. package/dist/transport.d.ts.map +1 -0
  93. package/dist/transport.js +74 -0
  94. package/dist/transport.js.map +1 -0
  95. package/package.json +72 -0
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Wire-format types for the v0.1 classification document.
3
+ *
4
+ * Schema tag: `mcp-recon/v0.1/classification`. Every field's design
5
+ * intent is documented in docs/METHODOLOGY.md.
6
+ */
7
+ /** Schema-version tag for classification documents. */
8
+ export declare const CLASSIFICATION_SCHEMA: "mcp-recon/v0.1/classification";
9
+ /** Top-level data classes, per docs/METHODOLOGY.md. */
10
+ export type DataClass = "filesystem" | "network" | "shell" | "payments" | "messaging" | "system" | "metadata" | "unknown";
11
+ /** Authority levels, per docs/METHODOLOGY.md. */
12
+ export type AuthorityLevel = "read" | "write" | "destructive" | "privileged";
13
+ /** One classification per tool. */
14
+ export interface Classification {
15
+ /** Tool name from the inventory. */
16
+ tool: string;
17
+ /** Assigned data-class. */
18
+ data_class: DataClass;
19
+ /** Assigned authority level. */
20
+ authority_level: AuthorityLevel;
21
+ /**
22
+ * The load-bearing flag: tool takes user-controllable string args
23
+ * AND has write/destructive/privileged authority.
24
+ */
25
+ confused_deputy_candidate: boolean;
26
+ /** Combined confidence in [0, 1] per noisy-OR over fired rules. */
27
+ confidence: number;
28
+ /** Free-form rationale listing every rule that fired and its weight. */
29
+ rationale: string;
30
+ /** Suggested capnagent caveat for this tool (string, copy-pasteable). */
31
+ recommended_caveat: string;
32
+ }
33
+ /** Top-level classification document. */
34
+ export interface ClassificationResults {
35
+ schema: typeof CLASSIFICATION_SCHEMA;
36
+ scanned_at: string;
37
+ server: {
38
+ name?: string;
39
+ version?: string;
40
+ };
41
+ /** Whether fuzz results were folded into confidence (raises confidence by 0.1). */
42
+ fuzz_informed: boolean;
43
+ classifications: Classification[];
44
+ }
45
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/classify/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,uDAAuD;AACvD,eAAO,MAAM,qBAAqB,EAAG,+BAAwC,CAAC;AAE9E,uDAAuD;AACvD,MAAM,MAAM,SAAS,GACjB,YAAY,GACZ,SAAS,GACT,OAAO,GACP,UAAU,GACV,WAAW,GACX,QAAQ,GACR,UAAU,GACV,SAAS,CAAC;AAEd,iDAAiD;AACjD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,YAAY,CAAC;AAE7E,mCAAmC;AACnC,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,UAAU,EAAE,SAAS,CAAC;IACtB,gCAAgC;IAChC,eAAe,EAAE,cAAc,CAAC;IAChC;;;OAGG;IACH,yBAAyB,EAAE,OAAO,CAAC;IACnC,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,yCAAyC;AACzC,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,qBAAqB,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,mFAAmF;IACnF,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,cAAc,EAAE,CAAC;CACnC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Wire-format types for the v0.1 classification document.
3
+ *
4
+ * Schema tag: `mcp-recon/v0.1/classification`. Every field's design
5
+ * intent is documented in docs/METHODOLOGY.md.
6
+ */
7
+ /** Schema-version tag for classification documents. */
8
+ export const CLASSIFICATION_SCHEMA = "mcp-recon/v0.1/classification";
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/classify/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,uDAAuD;AACvD,MAAM,CAAC,MAAM,qBAAqB,GAAG,+BAAwC,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * `enumerate` — produce a v0.1 tool inventory document.
3
+ *
4
+ * Connects to the server (caller's responsibility — pass an open
5
+ * Client) and lists every tool. Output shape is documented in
6
+ * docs/SPEC.md §"Output format". The shape is the load-bearing
7
+ * contract that downstream tools (capnagent's caveat-suggestion
8
+ * bridge, the Markdown reporter) consume.
9
+ */
10
+ import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
11
+ /** Schema-version tag for inventory documents. v0.1 = mcp-recon/v0.1/inventory. */
12
+ export declare const INVENTORY_SCHEMA: "mcp-recon/v0.1/inventory";
13
+ /** One tool as it appears in the inventory. */
14
+ export interface EnumeratedTool {
15
+ /** Tool name as the server reported it. */
16
+ name: string;
17
+ /** Optional human-readable description from the server. */
18
+ description?: string;
19
+ /** JSON Schema for the tool's input arguments — opaque to v0.1 enumerate. */
20
+ inputSchema: unknown;
21
+ }
22
+ /** A complete inventory document. */
23
+ export interface ToolInventory {
24
+ schema: typeof INVENTORY_SCHEMA;
25
+ scanned_at: string;
26
+ server: {
27
+ /** Whatever name the server self-identified as via initialize. */
28
+ name?: string;
29
+ /** Whatever version the server self-identified as. */
30
+ version?: string;
31
+ };
32
+ tools: EnumeratedTool[];
33
+ }
34
+ /**
35
+ * Options for `enumerate`.
36
+ *
37
+ * `timeoutMs` is forwarded to the SDK's `client.listTools` request
38
+ * options. Defaults to 30s — tighter than the SDK's 60s default,
39
+ * because mcp-recon scans untrusted servers and a hostile server
40
+ * that never replies should not hang the operator. Pass a smaller
41
+ * value when scripting against many servers; pass a larger value
42
+ * when scanning a slow but trusted server with a huge tool list.
43
+ *
44
+ * `maxDescriptionChars` bounds individual tool descriptions; longer
45
+ * values are truncated (with an `…[truncated by mcp-recon]` marker
46
+ * appended) before being stored in the inventory. Real-world tools
47
+ * have descriptions under 2KB; the 64KB default leaves headroom
48
+ * while bounding memory use of a hostile server returning a 10MB
49
+ * description in every tool. Pass `Infinity` to disable.
50
+ *
51
+ * Both options are discovered via `adversarial-servers/` fixtures
52
+ * (see `__tests__/adversarial.integration.test.ts`).
53
+ */
54
+ export interface EnumerateOptions {
55
+ /** Max time, in ms, to wait for `tools/list`. Default: 30000. */
56
+ timeoutMs?: number;
57
+ /** Per-tool description cap, in chars. Default: 65536. */
58
+ maxDescriptionChars?: number;
59
+ }
60
+ /** Default `tools/list` timeout. See `EnumerateOptions.timeoutMs`. */
61
+ export declare const DEFAULT_ENUMERATE_TIMEOUT_MS = 30000;
62
+ /** Default per-tool description cap. See `EnumerateOptions.maxDescriptionChars`. */
63
+ export declare const DEFAULT_MAX_DESCRIPTION_CHARS: number;
64
+ /** Marker appended to truncated descriptions so reviewers see the cap fired. */
65
+ export declare const TRUNCATION_MARKER = "\u2026[truncated by mcp-recon]";
66
+ /**
67
+ * Enumerate all tools exposed by the connected client.
68
+ *
69
+ * v0.1 is a thin shim over `client.listTools()` plus a self-
70
+ * describing wrapper. We do not classify here — that's the
71
+ * `classify` command's job. We do not fuzz here — that's `fuzz`.
72
+ * Single responsibility.
73
+ *
74
+ * Enforces a per-call timeout (`opts.timeoutMs`, default 30s) so a
75
+ * hostile server that accepts the handshake but never answers
76
+ * `tools/list` cannot hang the operator forever.
77
+ */
78
+ export declare function enumerate(client: Client, opts?: EnumerateOptions): Promise<ToolInventory>;
79
+ //# sourceMappingURL=enumerate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enumerate.d.ts","sourceRoot":"","sources":["../src/enumerate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAExE,mFAAmF;AACnF,eAAO,MAAM,gBAAgB,EAAG,0BAAmC,CAAC;AAEpE,+CAA+C;AAC/C,MAAM,WAAW,cAAc;IAC7B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,gBAAgB,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE;QACN,kEAAkE;QAClE,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,sDAAsD;QACtD,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,sEAAsE;AACtE,eAAO,MAAM,4BAA4B,QAAS,CAAC;AAEnD,oFAAoF;AACpF,eAAO,MAAM,6BAA6B,QAAY,CAAC;AAEvD,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,mCAA8B,CAAC;AAU7D;;;;;;;;;;;GAWG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,aAAa,CAAC,CAyBxB"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * `enumerate` — produce a v0.1 tool inventory document.
3
+ *
4
+ * Connects to the server (caller's responsibility — pass an open
5
+ * Client) and lists every tool. Output shape is documented in
6
+ * docs/SPEC.md §"Output format". The shape is the load-bearing
7
+ * contract that downstream tools (capnagent's caveat-suggestion
8
+ * bridge, the Markdown reporter) consume.
9
+ */
10
+ /** Schema-version tag for inventory documents. v0.1 = mcp-recon/v0.1/inventory. */
11
+ export const INVENTORY_SCHEMA = "mcp-recon/v0.1/inventory";
12
+ /** Default `tools/list` timeout. See `EnumerateOptions.timeoutMs`. */
13
+ export const DEFAULT_ENUMERATE_TIMEOUT_MS = 30_000;
14
+ /** Default per-tool description cap. See `EnumerateOptions.maxDescriptionChars`. */
15
+ export const DEFAULT_MAX_DESCRIPTION_CHARS = 64 * 1024;
16
+ /** Marker appended to truncated descriptions so reviewers see the cap fired. */
17
+ export const TRUNCATION_MARKER = "…[truncated by mcp-recon]";
18
+ function clampDescription(s, cap) {
19
+ if (s === undefined)
20
+ return undefined;
21
+ if (s.length <= cap)
22
+ return s;
23
+ // Reserve room for the marker so the final string is at most `cap`.
24
+ const room = Math.max(0, cap - TRUNCATION_MARKER.length);
25
+ return s.slice(0, room) + TRUNCATION_MARKER;
26
+ }
27
+ /**
28
+ * Enumerate all tools exposed by the connected client.
29
+ *
30
+ * v0.1 is a thin shim over `client.listTools()` plus a self-
31
+ * describing wrapper. We do not classify here — that's the
32
+ * `classify` command's job. We do not fuzz here — that's `fuzz`.
33
+ * Single responsibility.
34
+ *
35
+ * Enforces a per-call timeout (`opts.timeoutMs`, default 30s) so a
36
+ * hostile server that accepts the handshake but never answers
37
+ * `tools/list` cannot hang the operator forever.
38
+ */
39
+ export async function enumerate(client, opts = {}) {
40
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_ENUMERATE_TIMEOUT_MS;
41
+ const maxDescriptionChars = opts.maxDescriptionChars ?? DEFAULT_MAX_DESCRIPTION_CHARS;
42
+ const result = await client.listTools(undefined, { timeout: timeoutMs });
43
+ // The SDK exposes the server's identity via getServerVersion(); in
44
+ // some SDK versions this is an awaitable getter and in others a
45
+ // direct property. Probe defensively so we don't break across
46
+ // minor version bumps.
47
+ const serverInfo = client.getServerVersion?.();
48
+ return {
49
+ schema: INVENTORY_SCHEMA,
50
+ scanned_at: new Date().toISOString(),
51
+ server: {
52
+ name: serverInfo?.name,
53
+ version: serverInfo?.version,
54
+ },
55
+ tools: result.tools.map((t) => ({
56
+ name: t.name,
57
+ description: clampDescription(t.description, maxDescriptionChars),
58
+ inputSchema: t.inputSchema,
59
+ })),
60
+ };
61
+ }
62
+ //# sourceMappingURL=enumerate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enumerate.js","sourceRoot":"","sources":["../src/enumerate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,mFAAmF;AACnF,MAAM,CAAC,MAAM,gBAAgB,GAAG,0BAAmC,CAAC;AAoDpE,sEAAsE;AACtE,MAAM,CAAC,MAAM,4BAA4B,GAAG,MAAM,CAAC;AAEnD,oFAAoF;AACpF,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,GAAG,IAAI,CAAC;AAEvD,gFAAgF;AAChF,MAAM,CAAC,MAAM,iBAAiB,GAAG,2BAA2B,CAAC;AAE7D,SAAS,gBAAgB,CAAC,CAAqB,EAAE,GAAW;IAC1D,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACtC,IAAI,CAAC,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,CAAC,CAAC;IAC9B,oEAAoE;IACpE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzD,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,iBAAiB,CAAC;AAC9C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,MAAc,EACd,OAAyB,EAAE;IAE3B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,4BAA4B,CAAC;IACjE,MAAM,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,IAAI,6BAA6B,CAAC;IACtF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;IACzE,mEAAmE;IACnE,gEAAgE;IAChE,8DAA8D;IAC9D,uBAAuB;IACvB,MAAM,UAAU,GAAI,MAElB,CAAC,gBAAgB,EAAE,EAAE,CAAC;IAExB,OAAO;QACL,MAAM,EAAE,gBAAgB;QACxB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,MAAM,EAAE;YACN,IAAI,EAAE,UAAU,EAAE,IAAI;YACtB,OAAO,EAAE,UAAU,EAAE,OAAO;SAC7B;QACD,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9B,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,gBAAgB,CAAC,CAAC,CAAC,WAAW,EAAE,mBAAmB,CAAC;YACjE,WAAW,EAAE,CAAC,CAAC,WAAW;SAC3B,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Boundary-values axis.
3
+ *
4
+ * For each declared arg, generate edge values that often expose
5
+ * uninitialised handling: empty string, max-length string, 0, -1,
6
+ * Number.MAX_SAFE_INTEGER + 1, NaN, null, undefined-as-omitted.
7
+ *
8
+ * Per docs/SPEC.md §"Fuzzing strategy".
9
+ */
10
+ import type { Prng } from "../prng.js";
11
+ import type { ToolFacts } from "../schema.js";
12
+ /** Generate boundary inputs for one tool. */
13
+ export declare function generateBoundary(facts: ToolFacts, _prng: Prng): Generator<{
14
+ args: Record<string, unknown>;
15
+ rationale: string;
16
+ }>;
17
+ //# sourceMappingURL=boundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../../../src/fuzz/axes/boundary.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AA+B9C,6CAA6C;AAC7C,wBAAiB,gBAAgB,CAC/B,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,IAAI,GACV,SAAS,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAgCjE"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Boundary-values axis.
3
+ *
4
+ * For each declared arg, generate edge values that often expose
5
+ * uninitialised handling: empty string, max-length string, 0, -1,
6
+ * Number.MAX_SAFE_INTEGER + 1, NaN, null, undefined-as-omitted.
7
+ *
8
+ * Per docs/SPEC.md §"Fuzzing strategy".
9
+ */
10
+ const STRING_BOUNDARIES = [
11
+ "",
12
+ "x".repeat(1024 * 64), // 64 KiB
13
+ "\x00",
14
+ "\x00\x00\x00",
15
+ " ",
16
+ "\t\n\r",
17
+ ];
18
+ const NUMBER_BOUNDARIES = [
19
+ 0,
20
+ -1,
21
+ -0.0,
22
+ Number.MAX_SAFE_INTEGER + 1,
23
+ -Number.MAX_SAFE_INTEGER - 1,
24
+ Number.EPSILON,
25
+ Number.NaN,
26
+ Number.POSITIVE_INFINITY,
27
+ Number.NEGATIVE_INFINITY,
28
+ ];
29
+ const INTEGER_BOUNDARIES = [
30
+ 0,
31
+ -1,
32
+ Number.MAX_SAFE_INTEGER,
33
+ Number.MAX_SAFE_INTEGER + 1,
34
+ -Number.MAX_SAFE_INTEGER,
35
+ ];
36
+ /** Generate boundary inputs for one tool. */
37
+ export function* generateBoundary(facts, _prng) {
38
+ if (facts.isArgless) {
39
+ yield { args: {}, rationale: "argless tool: empty args object" };
40
+ return;
41
+ }
42
+ for (const arg of facts.args) {
43
+ const argName = arg.path[0];
44
+ if (argName === undefined)
45
+ continue;
46
+ const baseArgs = baseShape(facts);
47
+ const candidates = boundaryValuesFor(arg.declaredType);
48
+ for (const value of candidates) {
49
+ yield {
50
+ args: { ...baseArgs, [argName]: value },
51
+ rationale: `boundary ${arg.declaredType} for arg "${argName}": ${describeValue(value)}`,
52
+ };
53
+ }
54
+ }
55
+ // Whole-arg-missing: required field omitted.
56
+ for (const arg of facts.args) {
57
+ const argName = arg.path[0];
58
+ if (argName === undefined)
59
+ continue;
60
+ if (!arg.required)
61
+ continue;
62
+ const baseArgs = baseShape(facts);
63
+ delete baseArgs[argName];
64
+ yield {
65
+ args: baseArgs,
66
+ rationale: `boundary: omit required field "${argName}"`,
67
+ };
68
+ }
69
+ }
70
+ function boundaryValuesFor(t) {
71
+ switch (t) {
72
+ case "string":
73
+ return [...STRING_BOUNDARIES, null];
74
+ case "number":
75
+ return [...NUMBER_BOUNDARIES, null];
76
+ case "integer":
77
+ return [...INTEGER_BOUNDARIES, null];
78
+ case "boolean":
79
+ return [true, false, null];
80
+ case "array":
81
+ return [[], [null], Array.from({ length: 1024 }, (_, i) => i)];
82
+ case "object":
83
+ return [{}, { __proto__: null }, { a: { b: { c: { d: { e: 1 } } } } }];
84
+ case "null":
85
+ return [null];
86
+ case "unknown":
87
+ // For unknown-type args, throw the kitchen sink at it.
88
+ return ["", 0, true, [], {}, null];
89
+ }
90
+ }
91
+ function describeValue(v) {
92
+ if (v === null)
93
+ return "null";
94
+ if (Number.isNaN(v))
95
+ return "NaN";
96
+ if (v === Number.POSITIVE_INFINITY)
97
+ return "+Infinity";
98
+ if (v === Number.NEGATIVE_INFINITY)
99
+ return "-Infinity";
100
+ if (typeof v === "string") {
101
+ if (v.length === 0)
102
+ return "empty string";
103
+ if (v.length > 32)
104
+ return `string len=${v.length}`;
105
+ return JSON.stringify(v);
106
+ }
107
+ if (Array.isArray(v))
108
+ return `array len=${v.length}`;
109
+ return typeof v;
110
+ }
111
+ /** Build a "default" args shape so a single-field fuzz still has the other required fields populated. */
112
+ function baseShape(facts) {
113
+ const out = {};
114
+ for (const arg of facts.args) {
115
+ const argName = arg.path[0];
116
+ if (argName === undefined)
117
+ continue;
118
+ if (!arg.required)
119
+ continue;
120
+ out[argName] = defaultForType(arg.declaredType);
121
+ }
122
+ return out;
123
+ }
124
+ function defaultForType(t) {
125
+ switch (t) {
126
+ case "string":
127
+ return "x";
128
+ case "number":
129
+ case "integer":
130
+ return 1;
131
+ case "boolean":
132
+ return false;
133
+ case "array":
134
+ return [];
135
+ case "object":
136
+ return {};
137
+ case "null":
138
+ return null;
139
+ case "unknown":
140
+ return "x";
141
+ }
142
+ }
143
+ //# sourceMappingURL=boundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary.js","sourceRoot":"","sources":["../../../src/fuzz/axes/boundary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Encoding-tricks axis.
3
+ *
4
+ * For each string-typed arg, send variants that round-trip through
5
+ * common middleware in surprising ways: percent-encoded null bytes,
6
+ * Unicode homographs, RTL overrides, double-encoded sequences.
7
+ *
8
+ * Per docs/SPEC.md §"Fuzzing strategy".
9
+ */
10
+ import type { Prng } from "../prng.js";
11
+ import type { ToolFacts } from "../schema.js";
12
+ /** Generate encoding-trick inputs for one tool. */
13
+ export declare function generateEncoding(facts: ToolFacts, _prng: Prng): Generator<{
14
+ args: Record<string, unknown>;
15
+ rationale: string;
16
+ }>;
17
+ //# sourceMappingURL=encoding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoding.d.ts","sourceRoot":"","sources":["../../../src/fuzz/axes/encoding.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAqB9C,mDAAmD;AACnD,wBAAiB,gBAAgB,CAC/B,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,IAAI,GACV,SAAS,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAgBjE"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Encoding-tricks axis.
3
+ *
4
+ * For each string-typed arg, send variants that round-trip through
5
+ * common middleware in surprising ways: percent-encoded null bytes,
6
+ * Unicode homographs, RTL overrides, double-encoded sequences.
7
+ *
8
+ * Per docs/SPEC.md §"Fuzzing strategy".
9
+ */
10
+ const ENCODING_PAYLOADS = [
11
+ { value: "%00", reason: "percent-encoded NUL" },
12
+ { value: "%2e%2e", reason: "percent-encoded dot-dot" },
13
+ { value: "%252e%252e", reason: "double-percent-encoded dot-dot" },
14
+ { value: "x\x00y", reason: "embedded NUL byte" },
15
+ // Cyrillic homograph for ASCII 'a' (U+0430)
16
+ { value: "аdmin", reason: "Cyrillic-a homograph (admin)" },
17
+ // RTL override
18
+ { value: "‮gnp.exe", reason: "RTL override (filename spoof)" },
19
+ // Backslash escapes
20
+ { value: "\\..\\..\\..", reason: "backslash traversal" },
21
+ // Mixed slashes (Windows-style)
22
+ { value: "x\\y/z", reason: "mixed-separator path" },
23
+ // Unicode normalization edge — combining diacritics
24
+ { value: "café", reason: "combining diacritic (NFC vs NFD)" },
25
+ // Long string with one funny byte
26
+ { value: `${"a".repeat(1024)}\x00`, reason: "long string with trailing NUL" },
27
+ ];
28
+ /** Generate encoding-trick inputs for one tool. */
29
+ export function* generateEncoding(facts, _prng) {
30
+ if (facts.isArgless)
31
+ return;
32
+ for (const arg of facts.args) {
33
+ const argName = arg.path[0];
34
+ if (argName === undefined)
35
+ continue;
36
+ if (arg.declaredType !== "string" && arg.declaredType !== "unknown")
37
+ continue;
38
+ const baseArgs = baseShape(facts);
39
+ for (const { value, reason } of ENCODING_PAYLOADS) {
40
+ yield {
41
+ args: { ...baseArgs, [argName]: value },
42
+ rationale: `encoding "${argName}": ${reason}`,
43
+ };
44
+ }
45
+ }
46
+ }
47
+ function baseShape(facts) {
48
+ const out = {};
49
+ for (const arg of facts.args) {
50
+ const argName = arg.path[0];
51
+ if (argName === undefined)
52
+ continue;
53
+ if (!arg.required)
54
+ continue;
55
+ out[argName] = arg.declaredType === "string" ? "x" : 0;
56
+ }
57
+ return out;
58
+ }
59
+ //# sourceMappingURL=encoding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoding.js","sourceRoot":"","sources":["../../../src/fuzz/axes/encoding.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,iBAAiB,GAA6C;IAClE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,qBAAqB,EAAE;IAC/C,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,yBAAyB,EAAE;IACtD,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,gCAAgC,EAAE;IACjE,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,mBAAmB,EAAE;IAChD,4CAA4C;IAC5C,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,8BAA8B,EAAE;IAC1D,eAAe;IACf,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,+BAA+B,EAAE;IAC9D,oBAAoB;IACpB,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,qBAAqB,EAAE;IACxD,gCAAgC;IAChC,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,sBAAsB,EAAE;IACnD,oDAAoD;IACpD,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,kCAAkC,EAAE;IAC9D,kCAAkC;IAClC,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,+BAA+B,EAAE;CAC9E,CAAC;AAEF,mDAAmD;AACnD,MAAM,SAAS,CAAC,CAAC,gBAAgB,CAC/B,KAAgB,EAChB,KAAW;IAEX,IAAI,KAAK,CAAC,SAAS;QAAE,OAAO;IAE5B,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,OAAO,KAAK,SAAS;YAAE,SAAS;QACpC,IAAI,GAAG,CAAC,YAAY,KAAK,QAAQ,IAAI,GAAG,CAAC,YAAY,KAAK,SAAS;YAAE,SAAS;QAE9E,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QAClC,KAAK,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;YAClD,MAAM;gBACJ,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE;gBACvC,SAAS,EAAE,aAAa,OAAO,MAAM,MAAM,EAAE;aAC9C,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAgB;IACjC,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,OAAO,KAAK,SAAS;YAAE,SAAS;QACpC,IAAI,CAAC,GAAG,CAAC,QAAQ;YAAE,SAAS;QAC5B,GAAG,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Path-traversal axis.
3
+ *
4
+ * For each path-shaped arg (heuristic: name contains `path`, `file`,
5
+ * `dir`, etc. — see schema.ts::looksPathy), send classic traversal
6
+ * payloads. Tests whether the server canonicalises paths before use.
7
+ *
8
+ * Per docs/SPEC.md §"Fuzzing strategy".
9
+ */
10
+ import type { Prng } from "../prng.js";
11
+ import type { ToolFacts } from "../schema.js";
12
+ /** Generate path-traversal inputs for one tool. */
13
+ export declare function generatePathTraversal(facts: ToolFacts, _prng: Prng): Generator<{
14
+ args: Record<string, unknown>;
15
+ rationale: string;
16
+ }>;
17
+ //# sourceMappingURL=path-traversal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-traversal.d.ts","sourceRoot":"","sources":["../../../src/fuzz/axes/path-traversal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAgB9C,mDAAmD;AACnD,wBAAiB,qBAAqB,CACpC,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,IAAI,GACV,SAAS,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAiBjE"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Path-traversal axis.
3
+ *
4
+ * For each path-shaped arg (heuristic: name contains `path`, `file`,
5
+ * `dir`, etc. — see schema.ts::looksPathy), send classic traversal
6
+ * payloads. Tests whether the server canonicalises paths before use.
7
+ *
8
+ * Per docs/SPEC.md §"Fuzzing strategy".
9
+ */
10
+ const TRAVERSAL_PAYLOADS = [
11
+ { value: "../etc/passwd", reason: "POSIX dot-dot traversal" },
12
+ { value: "..\\..\\windows\\system32\\config\\sam", reason: "Windows dot-dot traversal" },
13
+ { value: "/etc/passwd", reason: "absolute POSIX path outside sandbox" },
14
+ { value: "C:\\Windows\\System32\\drivers\\etc\\hosts", reason: "absolute Windows path" },
15
+ { value: "/sandbox/../../../etc/passwd", reason: "in-sandbox prefix + traversal" },
16
+ { value: "/sandbox/%2e%2e/etc/passwd", reason: "percent-encoded traversal in path" },
17
+ { value: "//etc/passwd", reason: "double-slash absolute" },
18
+ { value: "/", reason: "filesystem root" },
19
+ { value: "~/.ssh/id_rsa", reason: "tilde-expansion private key" },
20
+ { value: "\\\\.\\PhysicalDrive0", reason: "Windows raw device path" },
21
+ { value: "file:///etc/passwd", reason: "file:// URI" },
22
+ ];
23
+ /** Generate path-traversal inputs for one tool. */
24
+ export function* generatePathTraversal(facts, _prng) {
25
+ if (facts.isArgless)
26
+ return;
27
+ for (const arg of facts.args) {
28
+ const argName = arg.path[0];
29
+ if (argName === undefined)
30
+ continue;
31
+ if (!arg.isPathShaped)
32
+ continue;
33
+ if (arg.declaredType !== "string" && arg.declaredType !== "unknown")
34
+ continue;
35
+ const baseArgs = baseShape(facts);
36
+ for (const { value, reason } of TRAVERSAL_PAYLOADS) {
37
+ yield {
38
+ args: { ...baseArgs, [argName]: value },
39
+ rationale: `path-traversal "${argName}": ${reason}`,
40
+ };
41
+ }
42
+ }
43
+ }
44
+ function baseShape(facts) {
45
+ const out = {};
46
+ for (const arg of facts.args) {
47
+ const argName = arg.path[0];
48
+ if (argName === undefined)
49
+ continue;
50
+ if (!arg.required)
51
+ continue;
52
+ out[argName] = arg.declaredType === "string" ? "x" : 0;
53
+ }
54
+ return out;
55
+ }
56
+ //# sourceMappingURL=path-traversal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-traversal.js","sourceRoot":"","sources":["../../../src/fuzz/axes/path-traversal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,kBAAkB,GAA6C;IACnE,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,yBAAyB,EAAE;IAC7D,EAAE,KAAK,EAAE,wCAAwC,EAAE,MAAM,EAAE,2BAA2B,EAAE;IACxF,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,qCAAqC,EAAE;IACvE,EAAE,KAAK,EAAE,4CAA4C,EAAE,MAAM,EAAE,uBAAuB,EAAE;IACxF,EAAE,KAAK,EAAE,8BAA8B,EAAE,MAAM,EAAE,+BAA+B,EAAE;IAClF,EAAE,KAAK,EAAE,4BAA4B,EAAE,MAAM,EAAE,mCAAmC,EAAE;IACpF,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,uBAAuB,EAAE;IAC1D,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,iBAAiB,EAAE;IACzC,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,6BAA6B,EAAE;IACjE,EAAE,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,yBAAyB,EAAE;IACrE,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,aAAa,EAAE;CACvD,CAAC;AAEF,mDAAmD;AACnD,MAAM,SAAS,CAAC,CAAC,qBAAqB,CACpC,KAAgB,EAChB,KAAW;IAEX,IAAI,KAAK,CAAC,SAAS;QAAE,OAAO;IAE5B,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,OAAO,KAAK,SAAS;YAAE,SAAS;QACpC,IAAI,CAAC,GAAG,CAAC,YAAY;YAAE,SAAS;QAChC,IAAI,GAAG,CAAC,YAAY,KAAK,QAAQ,IAAI,GAAG,CAAC,YAAY,KAAK,SAAS;YAAE,SAAS;QAE9E,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QAClC,KAAK,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,kBAAkB,EAAE,CAAC;YACnD,MAAM;gBACJ,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE;gBACvC,SAAS,EAAE,mBAAmB,OAAO,MAAM,MAAM,EAAE;aACpD,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAgB;IACjC,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,OAAO,KAAK,SAAS;YAAE,SAAS;QACpC,IAAI,CAAC,GAAG,CAAC,QAAQ;YAAE,SAAS;QAC5B,GAAG,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Schema-violation axis.
3
+ *
4
+ * Send args that violate the declared schema in structural ways:
5
+ * extra fields the schema doesn't mention, missing required fields,
6
+ * wrong types in nested positions, deeply-nested objects,
7
+ * prototype pollution shapes.
8
+ *
9
+ * Per docs/SPEC.md §"Fuzzing strategy".
10
+ */
11
+ import type { Prng } from "../prng.js";
12
+ import type { ToolFacts } from "../schema.js";
13
+ /** Generate schema-violation inputs for one tool. */
14
+ export declare function generateSchemaViolation(facts: ToolFacts, _prng: Prng): Generator<{
15
+ args: Record<string, unknown>;
16
+ rationale: string;
17
+ }>;
18
+ //# sourceMappingURL=schema-violation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-violation.d.ts","sourceRoot":"","sources":["../../../src/fuzz/axes/schema-violation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,qDAAqD;AACrD,wBAAiB,uBAAuB,CACtC,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,IAAI,GACV,SAAS,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA0CjE"}