@remnux/mcp-server 0.1.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 (220) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +720 -0
  3. package/dist/archive-extractor.d.ts +46 -0
  4. package/dist/archive-extractor.d.ts.map +1 -0
  5. package/dist/archive-extractor.js +268 -0
  6. package/dist/archive-extractor.js.map +1 -0
  7. package/dist/catalog/index.d.ts +40 -0
  8. package/dist/catalog/index.d.ts.map +1 -0
  9. package/dist/catalog/index.js +114 -0
  10. package/dist/catalog/index.js.map +1 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +154 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/config/archive-passwords.txt +3 -0
  16. package/dist/connectors/docker.d.ts +13 -0
  17. package/dist/connectors/docker.d.ts.map +1 -0
  18. package/dist/connectors/docker.js +201 -0
  19. package/dist/connectors/docker.js.map +1 -0
  20. package/dist/connectors/index.d.ts +27 -0
  21. package/dist/connectors/index.d.ts.map +1 -0
  22. package/dist/connectors/index.js +23 -0
  23. package/dist/connectors/index.js.map +1 -0
  24. package/dist/connectors/local.d.ts +10 -0
  25. package/dist/connectors/local.d.ts.map +1 -0
  26. package/dist/connectors/local.js +105 -0
  27. package/dist/connectors/local.js.map +1 -0
  28. package/dist/connectors/ssh.d.ts +21 -0
  29. package/dist/connectors/ssh.d.ts.map +1 -0
  30. package/dist/connectors/ssh.js +237 -0
  31. package/dist/connectors/ssh.js.map +1 -0
  32. package/dist/errors/error-mapper.d.ts +9 -0
  33. package/dist/errors/error-mapper.d.ts.map +1 -0
  34. package/dist/errors/error-mapper.js +24 -0
  35. package/dist/errors/error-mapper.js.map +1 -0
  36. package/dist/errors/remnux-error.d.ts +14 -0
  37. package/dist/errors/remnux-error.d.ts.map +1 -0
  38. package/dist/errors/remnux-error.js +19 -0
  39. package/dist/errors/remnux-error.js.map +1 -0
  40. package/dist/file-type-mappings.d.ts +30 -0
  41. package/dist/file-type-mappings.d.ts.map +1 -0
  42. package/dist/file-type-mappings.js +136 -0
  43. package/dist/file-type-mappings.js.map +1 -0
  44. package/dist/file-upload.d.ts +44 -0
  45. package/dist/file-upload.d.ts.map +1 -0
  46. package/dist/file-upload.js +170 -0
  47. package/dist/file-upload.js.map +1 -0
  48. package/dist/handlers/analyze-file.d.ts +10 -0
  49. package/dist/handlers/analyze-file.d.ts.map +1 -0
  50. package/dist/handlers/analyze-file.js +149 -0
  51. package/dist/handlers/analyze-file.js.map +1 -0
  52. package/dist/handlers/check-tools.d.ts +9 -0
  53. package/dist/handlers/check-tools.d.ts.map +1 -0
  54. package/dist/handlers/check-tools.js +47 -0
  55. package/dist/handlers/check-tools.js.map +1 -0
  56. package/dist/handlers/download-file.d.ts +10 -0
  57. package/dist/handlers/download-file.d.ts.map +1 -0
  58. package/dist/handlers/download-file.js +113 -0
  59. package/dist/handlers/download-file.js.map +1 -0
  60. package/dist/handlers/download-from-url.d.ts +30 -0
  61. package/dist/handlers/download-from-url.d.ts.map +1 -0
  62. package/dist/handlers/download-from-url.js +295 -0
  63. package/dist/handlers/download-from-url.js.map +1 -0
  64. package/dist/handlers/extract-archive.d.ts +10 -0
  65. package/dist/handlers/extract-archive.d.ts.map +1 -0
  66. package/dist/handlers/extract-archive.js +57 -0
  67. package/dist/handlers/extract-archive.js.map +1 -0
  68. package/dist/handlers/extract-iocs.d.ts +10 -0
  69. package/dist/handlers/extract-iocs.d.ts.map +1 -0
  70. package/dist/handlers/extract-iocs.js +21 -0
  71. package/dist/handlers/extract-iocs.js.map +1 -0
  72. package/dist/handlers/get-file-info.d.ts +10 -0
  73. package/dist/handlers/get-file-info.d.ts.map +1 -0
  74. package/dist/handlers/get-file-info.js +89 -0
  75. package/dist/handlers/get-file-info.js.map +1 -0
  76. package/dist/handlers/list-files.d.ts +10 -0
  77. package/dist/handlers/list-files.d.ts.map +1 -0
  78. package/dist/handlers/list-files.js +60 -0
  79. package/dist/handlers/list-files.js.map +1 -0
  80. package/dist/handlers/run-tool.d.ts +10 -0
  81. package/dist/handlers/run-tool.d.ts.map +1 -0
  82. package/dist/handlers/run-tool.js +99 -0
  83. package/dist/handlers/run-tool.js.map +1 -0
  84. package/dist/handlers/suggest-tools.d.ts +10 -0
  85. package/dist/handlers/suggest-tools.d.ts.map +1 -0
  86. package/dist/handlers/suggest-tools.js +202 -0
  87. package/dist/handlers/suggest-tools.js.map +1 -0
  88. package/dist/handlers/types.d.ts +15 -0
  89. package/dist/handlers/types.d.ts.map +1 -0
  90. package/dist/handlers/types.js +2 -0
  91. package/dist/handlers/types.js.map +1 -0
  92. package/dist/handlers/upload-file.d.ts +10 -0
  93. package/dist/handlers/upload-file.d.ts.map +1 -0
  94. package/dist/handlers/upload-file.js +33 -0
  95. package/dist/handlers/upload-file.js.map +1 -0
  96. package/dist/handlers/upload-from-host.d.ts +10 -0
  97. package/dist/handlers/upload-from-host.d.ts.map +1 -0
  98. package/dist/handlers/upload-from-host.js +33 -0
  99. package/dist/handlers/upload-from-host.js.map +1 -0
  100. package/dist/handlers/upload-sample.d.ts +10 -0
  101. package/dist/handlers/upload-sample.d.ts.map +1 -0
  102. package/dist/handlers/upload-sample.js +26 -0
  103. package/dist/handlers/upload-sample.js.map +1 -0
  104. package/dist/index.d.ts +15 -0
  105. package/dist/index.d.ts.map +1 -0
  106. package/dist/index.js +254 -0
  107. package/dist/index.js.map +1 -0
  108. package/dist/ioc/extractor.d.ts +21 -0
  109. package/dist/ioc/extractor.d.ts.map +1 -0
  110. package/dist/ioc/extractor.js +91 -0
  111. package/dist/ioc/extractor.js.map +1 -0
  112. package/dist/ioc/known-values.d.ts +7 -0
  113. package/dist/ioc/known-values.d.ts.map +1 -0
  114. package/dist/ioc/known-values.js +43 -0
  115. package/dist/ioc/known-values.js.map +1 -0
  116. package/dist/ioc/noise.d.ts +6 -0
  117. package/dist/ioc/noise.d.ts.map +1 -0
  118. package/dist/ioc/noise.js +170 -0
  119. package/dist/ioc/noise.js.map +1 -0
  120. package/dist/ioc/patterns.d.ts +10 -0
  121. package/dist/ioc/patterns.d.ts.map +1 -0
  122. package/dist/ioc/patterns.js +65 -0
  123. package/dist/ioc/patterns.js.map +1 -0
  124. package/dist/ioc/scoring.d.ts +6 -0
  125. package/dist/ioc/scoring.d.ts.map +1 -0
  126. package/dist/ioc/scoring.js +69 -0
  127. package/dist/ioc/scoring.js.map +1 -0
  128. package/dist/parsers/capa.d.ts +9 -0
  129. package/dist/parsers/capa.d.ts.map +1 -0
  130. package/dist/parsers/capa.js +55 -0
  131. package/dist/parsers/capa.js.map +1 -0
  132. package/dist/parsers/diec.d.ts +9 -0
  133. package/dist/parsers/diec.d.ts.map +1 -0
  134. package/dist/parsers/diec.js +53 -0
  135. package/dist/parsers/diec.js.map +1 -0
  136. package/dist/parsers/floss.d.ts +14 -0
  137. package/dist/parsers/floss.d.ts.map +1 -0
  138. package/dist/parsers/floss.js +89 -0
  139. package/dist/parsers/floss.js.map +1 -0
  140. package/dist/parsers/index.d.ts +16 -0
  141. package/dist/parsers/index.d.ts.map +1 -0
  142. package/dist/parsers/index.js +46 -0
  143. package/dist/parsers/index.js.map +1 -0
  144. package/dist/parsers/oleid.d.ts +8 -0
  145. package/dist/parsers/oleid.d.ts.map +1 -0
  146. package/dist/parsers/oleid.js +94 -0
  147. package/dist/parsers/oleid.js.map +1 -0
  148. package/dist/parsers/olevba.d.ts +8 -0
  149. package/dist/parsers/olevba.d.ts.map +1 -0
  150. package/dist/parsers/olevba.js +83 -0
  151. package/dist/parsers/olevba.js.map +1 -0
  152. package/dist/parsers/passthrough.d.ts +6 -0
  153. package/dist/parsers/passthrough.d.ts.map +1 -0
  154. package/dist/parsers/passthrough.js +13 -0
  155. package/dist/parsers/passthrough.js.map +1 -0
  156. package/dist/parsers/pdf-parser.d.ts +9 -0
  157. package/dist/parsers/pdf-parser.d.ts.map +1 -0
  158. package/dist/parsers/pdf-parser.js +76 -0
  159. package/dist/parsers/pdf-parser.js.map +1 -0
  160. package/dist/parsers/pdfid.d.ts +9 -0
  161. package/dist/parsers/pdfid.d.ts.map +1 -0
  162. package/dist/parsers/pdfid.js +56 -0
  163. package/dist/parsers/pdfid.js.map +1 -0
  164. package/dist/parsers/peframe.d.ts +8 -0
  165. package/dist/parsers/peframe.d.ts.map +1 -0
  166. package/dist/parsers/peframe.js +76 -0
  167. package/dist/parsers/peframe.js.map +1 -0
  168. package/dist/parsers/readelf.d.ts +8 -0
  169. package/dist/parsers/readelf.d.ts.map +1 -0
  170. package/dist/parsers/readelf.js +50 -0
  171. package/dist/parsers/readelf.js.map +1 -0
  172. package/dist/parsers/types.d.ts +30 -0
  173. package/dist/parsers/types.d.ts.map +1 -0
  174. package/dist/parsers/types.js +5 -0
  175. package/dist/parsers/types.js.map +1 -0
  176. package/dist/parsers/yara.d.ts +8 -0
  177. package/dist/parsers/yara.d.ts.map +1 -0
  178. package/dist/parsers/yara.js +88 -0
  179. package/dist/parsers/yara.js.map +1 -0
  180. package/dist/response.d.ts +44 -0
  181. package/dist/response.d.ts.map +1 -0
  182. package/dist/response.js +48 -0
  183. package/dist/response.js.map +1 -0
  184. package/dist/schemas/tools.d.ts +135 -0
  185. package/dist/schemas/tools.d.ts.map +1 -0
  186. package/dist/schemas/tools.js +53 -0
  187. package/dist/schemas/tools.js.map +1 -0
  188. package/dist/security/blocklist.d.ts +69 -0
  189. package/dist/security/blocklist.d.ts.map +1 -0
  190. package/dist/security/blocklist.js +148 -0
  191. package/dist/security/blocklist.js.map +1 -0
  192. package/dist/state/session.d.ts +35 -0
  193. package/dist/state/session.d.ts.map +1 -0
  194. package/dist/state/session.js +45 -0
  195. package/dist/state/session.js.map +1 -0
  196. package/dist/tools/definitions.d.ts +9 -0
  197. package/dist/tools/definitions.d.ts.map +1 -0
  198. package/dist/tools/definitions.js +708 -0
  199. package/dist/tools/definitions.js.map +1 -0
  200. package/dist/tools/invoker.d.ts +17 -0
  201. package/dist/tools/invoker.d.ts.map +1 -0
  202. package/dist/tools/invoker.js +44 -0
  203. package/dist/tools/invoker.js.map +1 -0
  204. package/dist/tools/registry.d.ts +62 -0
  205. package/dist/tools/registry.d.ts.map +1 -0
  206. package/dist/tools/registry.js +53 -0
  207. package/dist/tools/registry.js.map +1 -0
  208. package/dist/workflows/engine.d.ts +27 -0
  209. package/dist/workflows/engine.d.ts.map +1 -0
  210. package/dist/workflows/engine.js +224 -0
  211. package/dist/workflows/engine.js.map +1 -0
  212. package/dist/workflows/loader.d.ts +33 -0
  213. package/dist/workflows/loader.d.ts.map +1 -0
  214. package/dist/workflows/loader.js +130 -0
  215. package/dist/workflows/loader.js.map +1 -0
  216. package/dist/workflows/types.d.ts +109 -0
  217. package/dist/workflows/types.d.ts.map +1 -0
  218. package/dist/workflows/types.js +5 -0
  219. package/dist/workflows/types.js.map +1 -0
  220. package/package.json +68 -0
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Standardized JSON response envelope for all MCP tool handlers.
3
+ *
4
+ * Every tool returns { success, tool, data, metadata } so callers
5
+ * get a predictable shape regardless of which tool was invoked.
6
+ */
7
+ import type { ErrorCategory } from "./errors/remnux-error.js";
8
+ import { REMnuxError } from "./errors/remnux-error.js";
9
+ export interface ToolResponse {
10
+ success: boolean;
11
+ tool: string;
12
+ data: Record<string, unknown>;
13
+ error?: string;
14
+ error_code?: string;
15
+ error_category?: ErrorCategory;
16
+ remediation?: string;
17
+ metadata: {
18
+ elapsed_ms: number;
19
+ };
20
+ }
21
+ /**
22
+ * Build a success response envelope.
23
+ */
24
+ export declare function formatResponse(tool: string, data: Record<string, unknown>, startTime: number): {
25
+ content: Array<{
26
+ type: "text";
27
+ text: string;
28
+ }>;
29
+ isError?: boolean;
30
+ };
31
+ /**
32
+ * Build an error response envelope. Sets `isError: true` on the MCP result.
33
+ *
34
+ * When `error` is a REMnuxError, the envelope includes structured fields:
35
+ * error_code, error_category, and remediation.
36
+ */
37
+ export declare function formatError(tool: string, error: string | REMnuxError, startTime: number): {
38
+ content: Array<{
39
+ type: "text";
40
+ text: string;
41
+ }>;
42
+ isError: true;
43
+ };
44
+ //# sourceMappingURL=response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../src/response.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE;QACR,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,SAAS,EAAE,MAAM,GAChB;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAUvE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GAAG,WAAW,EAC3B,SAAS,EAAE,MAAM,GAChB;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,CAqBnE"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Standardized JSON response envelope for all MCP tool handlers.
3
+ *
4
+ * Every tool returns { success, tool, data, metadata } so callers
5
+ * get a predictable shape regardless of which tool was invoked.
6
+ */
7
+ import { REMnuxError } from "./errors/remnux-error.js";
8
+ /**
9
+ * Build a success response envelope.
10
+ */
11
+ export function formatResponse(tool, data, startTime) {
12
+ const envelope = {
13
+ success: true,
14
+ tool,
15
+ data,
16
+ metadata: { elapsed_ms: Date.now() - startTime },
17
+ };
18
+ return {
19
+ content: [{ type: "text", text: JSON.stringify(envelope, null, 2) }],
20
+ };
21
+ }
22
+ /**
23
+ * Build an error response envelope. Sets `isError: true` on the MCP result.
24
+ *
25
+ * When `error` is a REMnuxError, the envelope includes structured fields:
26
+ * error_code, error_category, and remediation.
27
+ */
28
+ export function formatError(tool, error, startTime) {
29
+ const envelope = {
30
+ success: false,
31
+ tool,
32
+ data: {},
33
+ error: error instanceof REMnuxError ? error.message : error,
34
+ metadata: { elapsed_ms: Date.now() - startTime },
35
+ };
36
+ if (error instanceof REMnuxError) {
37
+ envelope.error_code = error.code;
38
+ envelope.error_category = error.category;
39
+ if (error.remediation) {
40
+ envelope.remediation = error.remediation;
41
+ }
42
+ }
43
+ return {
44
+ content: [{ type: "text", text: JSON.stringify(envelope, null, 2) }],
45
+ isError: true,
46
+ };
47
+ }
48
+ //# sourceMappingURL=response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response.js","sourceRoot":"","sources":["../src/response.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAevD;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,IAA6B,EAC7B,SAAiB;IAEjB,MAAM,QAAQ,GAAiB;QAC7B,OAAO,EAAE,IAAI;QACb,IAAI;QACJ,IAAI;QACJ,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE;KACjD,CAAC;IACF,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KACrE,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,IAAY,EACZ,KAA2B,EAC3B,SAAiB;IAEjB,MAAM,QAAQ,GAAiB;QAC7B,OAAO,EAAE,KAAK;QACd,IAAI;QACJ,IAAI,EAAE,EAAE;QACR,KAAK,EAAE,KAAK,YAAY,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;QAC3D,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE;KACjD,CAAC;IAEF,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;QACjC,QAAQ,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC;QACjC,QAAQ,CAAC,cAAc,GAAG,KAAK,CAAC,QAAQ,CAAC;QACzC,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,QAAQ,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QACpE,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC"}
@@ -0,0 +1,135 @@
1
+ import { z } from "zod";
2
+ export declare const runToolSchema: z.ZodObject<{
3
+ command: z.ZodString;
4
+ input_file: z.ZodOptional<z.ZodString>;
5
+ timeout: z.ZodOptional<z.ZodNumber>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ command: string;
8
+ timeout?: number | undefined;
9
+ input_file?: string | undefined;
10
+ }, {
11
+ command: string;
12
+ timeout?: number | undefined;
13
+ input_file?: string | undefined;
14
+ }>;
15
+ export type RunToolArgs = z.infer<typeof runToolSchema>;
16
+ export declare const getFileInfoSchema: z.ZodObject<{
17
+ file: z.ZodString;
18
+ }, "strip", z.ZodTypeAny, {
19
+ file: string;
20
+ }, {
21
+ file: string;
22
+ }>;
23
+ export type GetFileInfoArgs = z.infer<typeof getFileInfoSchema>;
24
+ export declare const listFilesSchema: z.ZodObject<{
25
+ directory: z.ZodDefault<z.ZodEnum<["samples", "output"]>>;
26
+ }, "strip", z.ZodTypeAny, {
27
+ directory: "samples" | "output";
28
+ }, {
29
+ directory?: "samples" | "output" | undefined;
30
+ }>;
31
+ export type ListFilesArgs = z.infer<typeof listFilesSchema>;
32
+ export declare const extractArchiveSchema: z.ZodObject<{
33
+ archive_file: z.ZodString;
34
+ password: z.ZodOptional<z.ZodString>;
35
+ output_subdir: z.ZodOptional<z.ZodString>;
36
+ }, "strip", z.ZodTypeAny, {
37
+ archive_file: string;
38
+ password?: string | undefined;
39
+ output_subdir?: string | undefined;
40
+ }, {
41
+ archive_file: string;
42
+ password?: string | undefined;
43
+ output_subdir?: string | undefined;
44
+ }>;
45
+ export type ExtractArchiveArgs = z.infer<typeof extractArchiveSchema>;
46
+ export declare const uploadFromHostSchema: z.ZodObject<{
47
+ host_path: z.ZodString;
48
+ filename: z.ZodOptional<z.ZodString>;
49
+ overwrite: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
50
+ }, "strip", z.ZodTypeAny, {
51
+ host_path: string;
52
+ overwrite: boolean;
53
+ filename?: string | undefined;
54
+ }, {
55
+ host_path: string;
56
+ filename?: string | undefined;
57
+ overwrite?: boolean | undefined;
58
+ }>;
59
+ export type UploadFromHostArgs = z.infer<typeof uploadFromHostSchema>;
60
+ export declare const downloadFileSchema: z.ZodObject<{
61
+ file_path: z.ZodString;
62
+ output_path: z.ZodString;
63
+ archive: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
64
+ }, "strip", z.ZodTypeAny, {
65
+ file_path: string;
66
+ output_path: string;
67
+ archive: boolean;
68
+ }, {
69
+ file_path: string;
70
+ output_path: string;
71
+ archive?: boolean | undefined;
72
+ }>;
73
+ export type DownloadFileArgs = z.input<typeof downloadFileSchema>;
74
+ export declare const analyzeFileSchema: z.ZodObject<{
75
+ file: z.ZodString;
76
+ timeout_per_tool: z.ZodOptional<z.ZodNumber>;
77
+ depth: z.ZodDefault<z.ZodOptional<z.ZodEnum<["quick", "standard", "deep"]>>>;
78
+ }, "strip", z.ZodTypeAny, {
79
+ file: string;
80
+ depth: "quick" | "standard" | "deep";
81
+ timeout_per_tool?: number | undefined;
82
+ }, {
83
+ file: string;
84
+ timeout_per_tool?: number | undefined;
85
+ depth?: "quick" | "standard" | "deep" | undefined;
86
+ }>;
87
+ export type AnalyzeFileArgs = z.input<typeof analyzeFileSchema>;
88
+ export declare const checkToolsSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
89
+ export type CheckToolsArgs = z.infer<typeof checkToolsSchema>;
90
+ export declare const suggestToolsSchema: z.ZodObject<{
91
+ file: z.ZodString;
92
+ depth: z.ZodDefault<z.ZodOptional<z.ZodEnum<["quick", "standard", "deep"]>>>;
93
+ }, "strip", z.ZodTypeAny, {
94
+ file: string;
95
+ depth: "quick" | "standard" | "deep";
96
+ }, {
97
+ file: string;
98
+ depth?: "quick" | "standard" | "deep" | undefined;
99
+ }>;
100
+ export type SuggestToolsArgs = z.input<typeof suggestToolsSchema>;
101
+ export declare const downloadFromUrlSchema: z.ZodObject<{
102
+ url: z.ZodString;
103
+ filename: z.ZodOptional<z.ZodString>;
104
+ headers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
105
+ method: z.ZodDefault<z.ZodOptional<z.ZodEnum<["curl", "thug"]>>>;
106
+ overwrite: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
107
+ timeout: z.ZodOptional<z.ZodNumber>;
108
+ }, "strip", z.ZodTypeAny, {
109
+ overwrite: boolean;
110
+ url: string;
111
+ method: "curl" | "thug";
112
+ timeout?: number | undefined;
113
+ filename?: string | undefined;
114
+ headers?: string[] | undefined;
115
+ }, {
116
+ url: string;
117
+ timeout?: number | undefined;
118
+ filename?: string | undefined;
119
+ overwrite?: boolean | undefined;
120
+ headers?: string[] | undefined;
121
+ method?: "curl" | "thug" | undefined;
122
+ }>;
123
+ export type DownloadFromUrlArgs = z.input<typeof downloadFromUrlSchema>;
124
+ export declare const extractIOCsSchema: z.ZodObject<{
125
+ text: z.ZodString;
126
+ include_noise: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
127
+ }, "strip", z.ZodTypeAny, {
128
+ text: string;
129
+ include_noise: boolean;
130
+ }, {
131
+ text: string;
132
+ include_noise?: boolean | undefined;
133
+ }>;
134
+ export type ExtractIOCsArgs = z.infer<typeof extractIOCsSchema>;
135
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/schemas/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,aAAa;;;;;;;;;;;;EAIxB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAExD,eAAO,MAAM,iBAAiB;;;;;;EAE5B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEhE,eAAO,MAAM,eAAe;;;;;;EAE1B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE5D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;EAI/B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEtE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;EAI/B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEtE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;EAO7B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAElE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;EAM5B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEhE,eAAO,MAAM,gBAAgB,gDAAe,CAAC;AAC7C,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE9D,eAAO,MAAM,kBAAkB;;;;;;;;;EAK7B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAElE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;EAmBhC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAExE,eAAO,MAAM,iBAAiB;;;;;;;;;EAG5B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { z } from "zod";
2
+ export const runToolSchema = z.object({
3
+ command: z.string().describe("Command to execute (can include pipes, e.g., 'strings sample.exe | grep -i password')"),
4
+ input_file: z.string().optional().describe("Input file path (relative to samples dir) - appended to command"),
5
+ timeout: z.number().optional().describe("Timeout in seconds (default: 300)"),
6
+ });
7
+ export const getFileInfoSchema = z.object({
8
+ file: z.string().describe("File path relative to samples directory"),
9
+ });
10
+ export const listFilesSchema = z.object({
11
+ directory: z.enum(["samples", "output"]).default("samples").describe("Which directory to list"),
12
+ });
13
+ export const extractArchiveSchema = z.object({
14
+ archive_file: z.string().describe("Path to archive file relative to samples directory (e.g., 'sample.zip')"),
15
+ password: z.string().optional().describe("Optional password to try first. If not provided, tries common passwords from built-in list."),
16
+ output_subdir: z.string().optional().describe("Optional subdirectory name for extracted files. Defaults to archive filename without extension."),
17
+ });
18
+ export const uploadFromHostSchema = z.object({
19
+ host_path: z.string().describe("Absolute path on the host filesystem to the file to upload"),
20
+ filename: z.string().optional().describe("Override filename in samples dir (defaults to basename of host_path)"),
21
+ overwrite: z.boolean().optional().default(false).describe("Whether to overwrite if file exists. Default: false"),
22
+ });
23
+ export const downloadFileSchema = z.object({
24
+ file_path: z.string().describe("File path relative to the output directory"),
25
+ output_path: z.string().describe("Directory on host to save the downloaded file"),
26
+ archive: z.boolean().optional().default(true).describe("Wrap the file in a password-protected archive before transfer (default: true). " +
27
+ "Protects against AV/EDR triggers on the host. Pass false for harmless files like text reports."),
28
+ });
29
+ export const analyzeFileSchema = z.object({
30
+ file: z.string().describe("Filename relative to samples directory"),
31
+ timeout_per_tool: z.number().optional().describe("Timeout per tool in seconds (default: 60)"),
32
+ depth: z.enum(["quick", "standard", "deep"]).optional().default("standard").describe("Analysis depth: 'quick' (fast triage tools only), 'standard' (default, all category tools), 'deep' (standard + expensive tools like full decompilation)"),
33
+ });
34
+ export const checkToolsSchema = z.object({});
35
+ export const suggestToolsSchema = z.object({
36
+ file: z.string().describe("Filename relative to samples directory"),
37
+ depth: z.enum(["quick", "standard", "deep"]).optional().default("standard").describe("Filter recommendations by depth tier: 'quick' (triage only), 'standard' (default), 'deep' (all tools)"),
38
+ });
39
+ export const downloadFromUrlSchema = z.object({
40
+ url: z.string().url().describe("URL to download (http or https only)"),
41
+ filename: z.string().optional().describe("Override filename in samples dir. If omitted, derived from URL path."),
42
+ headers: z.array(z.string()).optional().describe("Custom HTTP headers as 'Name: value' strings. " +
43
+ "Example: ['User-Agent: Mozilla/5.0', 'X-Auth-Token: abc123']"),
44
+ method: z.enum(["curl", "thug"]).optional().default("curl").describe("Download method. 'curl' (default) for direct HTTP download. " +
45
+ "'thug' for sites requiring JavaScript execution (uses thug honeyclient)."),
46
+ overwrite: z.boolean().optional().default(false).describe("Whether to overwrite if file exists. Default: false"),
47
+ timeout: z.number().optional().describe("Download timeout in seconds (default: server timeout)"),
48
+ });
49
+ export const extractIOCsSchema = z.object({
50
+ text: z.string().describe("Text to extract IOCs from (e.g., output from run_tool or analyze_file)"),
51
+ include_noise: z.boolean().optional().default(false).describe("Include low-confidence known-good IOCs"),
52
+ });
53
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/schemas/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Security configuration for REMnux MCP server
3
+ *
4
+ * Threat model: All three modes (docker, ssh, local) execute commands inside a
5
+ * disposable REMnux VM or container. Container/VM isolation is the security
6
+ * boundary — not this module.
7
+ *
8
+ * This module prevents:
9
+ * 1. Shell injection — malware output containing prompt injection could trick
10
+ * the AI into executing arbitrary code via eval, $(), backticks, etc.
11
+ * 2. Dangerous pipes — pipes to interpreters (| bash, | python) blocked.
12
+ *
13
+ * Path sandboxing (isPathSafe, validateFilePath) is available as an opt-in
14
+ * workflow aid via --sandbox, not as a security control.
15
+ */
16
+ /**
17
+ * Blocked command patterns
18
+ * Commands matching these patterns will be rejected regardless of tool
19
+ */
20
+ export interface BlockedPattern {
21
+ pattern: RegExp;
22
+ category: string;
23
+ }
24
+ export declare const BLOCKED_PATTERNS: BlockedPattern[];
25
+ /**
26
+ * Validate that a path is safe (within allowed directories)
27
+ * @param path - The path to validate (relative to baseDir)
28
+ * @param baseDir - The base directory that the path should be contained within
29
+ * @returns true if the path is safe, false otherwise
30
+ */
31
+ export declare function isPathSafe(path: string, baseDir: string): boolean;
32
+ /**
33
+ * Check if a path is a symlink
34
+ *
35
+ * @param filePath - The full path to check (already resolved)
36
+ * @returns true if the path is a symlink, false otherwise
37
+ * @throws Error if the path doesn't exist
38
+ */
39
+ export declare function isSymlink(filePath: string): boolean;
40
+ /**
41
+ * Validate a file path for safe execution
42
+ * Checks path safety (no traversal, no special chars, stays within baseDir)
43
+ *
44
+ * @param relativePath - Relative path from baseDir
45
+ * @param baseDir - Base directory
46
+ * @returns { safe: boolean, error?: string }
47
+ */
48
+ export declare function validateFilePath(relativePath: string, baseDir: string): {
49
+ safe: boolean;
50
+ error?: string;
51
+ };
52
+ /**
53
+ * Dangerous pipe patterns - commands piped to interpreters that could execute code
54
+ * These are checked separately to allow safe pipes (e.g., grep, head, sort)
55
+ * while blocking dangerous ones (e.g., | bash, | python)
56
+ */
57
+ export declare const DANGEROUS_PIPE_PATTERNS: BlockedPattern[];
58
+ /**
59
+ * Check if a command string is safe to execute
60
+ * Validates against both BLOCKED_PATTERNS and DANGEROUS_PIPE_PATTERNS
61
+ *
62
+ * @param command - The full command string to validate
63
+ * @returns { safe: boolean, error?: string }
64
+ */
65
+ export declare function isCommandSafe(command: string): {
66
+ safe: boolean;
67
+ error?: string;
68
+ };
69
+ //# sourceMappingURL=blocklist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocklist.d.ts","sourceRoot":"","sources":["../../src/security/blocklist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,gBAAgB,EAAE,cAAc,EAuB5C,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAmCjE;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,GACd;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAMnC;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,cAAc,EAWnD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAqBhF"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Security configuration for REMnux MCP server
3
+ *
4
+ * Threat model: All three modes (docker, ssh, local) execute commands inside a
5
+ * disposable REMnux VM or container. Container/VM isolation is the security
6
+ * boundary — not this module.
7
+ *
8
+ * This module prevents:
9
+ * 1. Shell injection — malware output containing prompt injection could trick
10
+ * the AI into executing arbitrary code via eval, $(), backticks, etc.
11
+ * 2. Dangerous pipes — pipes to interpreters (| bash, | python) blocked.
12
+ *
13
+ * Path sandboxing (isPathSafe, validateFilePath) is available as an opt-in
14
+ * workflow aid via --sandbox, not as a security control.
15
+ */
16
+ import { normalize, isAbsolute, resolve } from "path";
17
+ import { lstatSync, existsSync } from "fs";
18
+ export const BLOCKED_PATTERNS = [
19
+ // CRITICAL: Newline and control character injection
20
+ { pattern: /[\n\r\x00]/, category: "control character injection" },
21
+ // Shell escape / code execution — prevents prompt injection from triggering arbitrary code
22
+ { pattern: /\beval\b/i, category: "shell escape" },
23
+ { pattern: /\bexec\b/i, category: "shell escape" },
24
+ { pattern: /`[^`]+`/, category: "shell escape (backtick)" },
25
+ { pattern: /\$\([^)]+\)/, category: "shell escape (command substitution)" },
26
+ { pattern: /\$\{[^}]+\}/, category: "shell escape (variable expansion)" },
27
+ { pattern: /\$[A-Za-z_][A-Za-z0-9_]*/, category: "shell escape (variable expansion)" },
28
+ // Process substitution
29
+ { pattern: /[<>]\s*\(/, category: "process substitution" },
30
+ // Shell sourcing
31
+ { pattern: /\bsource\b/i, category: "shell escape" },
32
+ // Catastrophic command guard — prevents AI from accidentally destroying the analysis session
33
+ // Only blocks root-level wipes (rm -rf /), not targeted deletes (rm -rf subdir/)
34
+ { pattern: /rm\s+-[rR].*\s\/\s*$/, category: "catastrophic command (root wipe)" },
35
+ { pattern: /rm\s+-[rR].*\s\/\*/, category: "catastrophic command (root wipe)" },
36
+ { pattern: /\bmkfs\b/, category: "catastrophic command (format filesystem)" },
37
+ ];
38
+ /**
39
+ * Validate that a path is safe (within allowed directories)
40
+ * @param path - The path to validate (relative to baseDir)
41
+ * @param baseDir - The base directory that the path should be contained within
42
+ * @returns true if the path is safe, false otherwise
43
+ */
44
+ export function isPathSafe(path, baseDir) {
45
+ // Reject empty string (resolves to baseDir itself)
46
+ if (path === "")
47
+ return false;
48
+ // Reject null bytes (can truncate paths in C-based functions)
49
+ if (path.includes("\0"))
50
+ return false;
51
+ // Reject absolute paths
52
+ if (isAbsolute(path))
53
+ return false;
54
+ // Reject path traversal (check before normalization)
55
+ if (path.includes(".."))
56
+ return false;
57
+ // Reject special characters that might cause shell issues
58
+ if (/[;&|`$\n\r'"]/.test(path))
59
+ return false;
60
+ // Reject home directory references
61
+ if (path.startsWith("~"))
62
+ return false;
63
+ // Normalize the path to handle unicode normalization attacks
64
+ const normalizedPath = normalize(path);
65
+ // After normalization, check again for traversal (handles cases like "foo/../..")
66
+ if (normalizedPath.includes("..") || normalizedPath.startsWith(".."))
67
+ return false;
68
+ // Verify the resolved path stays within baseDir
69
+ const resolvedPath = resolve(baseDir, normalizedPath);
70
+ const normalizedBase = resolve(baseDir);
71
+ // The resolved path must start with the base directory
72
+ if (!resolvedPath.startsWith(normalizedBase + "/") && resolvedPath !== normalizedBase) {
73
+ return false;
74
+ }
75
+ return true;
76
+ }
77
+ /**
78
+ * Check if a path is a symlink
79
+ *
80
+ * @param filePath - The full path to check (already resolved)
81
+ * @returns true if the path is a symlink, false otherwise
82
+ * @throws Error if the path doesn't exist
83
+ */
84
+ export function isSymlink(filePath) {
85
+ if (!existsSync(filePath)) {
86
+ throw new Error(`Path does not exist: ${filePath}`);
87
+ }
88
+ const stats = lstatSync(filePath);
89
+ return stats.isSymbolicLink();
90
+ }
91
+ /**
92
+ * Validate a file path for safe execution
93
+ * Checks path safety (no traversal, no special chars, stays within baseDir)
94
+ *
95
+ * @param relativePath - Relative path from baseDir
96
+ * @param baseDir - Base directory
97
+ * @returns { safe: boolean, error?: string }
98
+ */
99
+ export function validateFilePath(relativePath, baseDir) {
100
+ if (!isPathSafe(relativePath, baseDir)) {
101
+ return { safe: false, error: "Invalid file path" };
102
+ }
103
+ return { safe: true };
104
+ }
105
+ /**
106
+ * Dangerous pipe patterns - commands piped to interpreters that could execute code
107
+ * These are checked separately to allow safe pipes (e.g., grep, head, sort)
108
+ * while blocking dangerous ones (e.g., | bash, | python)
109
+ */
110
+ export const DANGEROUS_PIPE_PATTERNS = [
111
+ // Pipe to code interpreters — prevents prompt injection from executing arbitrary code
112
+ { pattern: /\|\s*(ba)?sh\b/i, category: "pipe to shell" },
113
+ { pattern: /\|\s*zsh\b/i, category: "pipe to shell" },
114
+ { pattern: /\|\s*fish\b/i, category: "pipe to shell" },
115
+ { pattern: /\|\s*python[23]?\b/i, category: "pipe to interpreter" },
116
+ { pattern: /\|\s*perl\b/i, category: "pipe to interpreter" },
117
+ { pattern: /\|\s*ruby\b/i, category: "pipe to interpreter" },
118
+ { pattern: /\|\s*node\b/i, category: "pipe to interpreter" },
119
+ { pattern: /\|\s*php\b/i, category: "pipe to interpreter" },
120
+ { pattern: /\|\s*lua\b/i, category: "pipe to interpreter" },
121
+ ];
122
+ /**
123
+ * Check if a command string is safe to execute
124
+ * Validates against both BLOCKED_PATTERNS and DANGEROUS_PIPE_PATTERNS
125
+ *
126
+ * @param command - The full command string to validate
127
+ * @returns { safe: boolean, error?: string }
128
+ */
129
+ export function isCommandSafe(command) {
130
+ // Reject empty or whitespace-only commands
131
+ if (!command || command.trim() === "") {
132
+ return { safe: false, error: "Empty command" };
133
+ }
134
+ // Check against blocked patterns
135
+ for (const { pattern, category } of BLOCKED_PATTERNS) {
136
+ if (pattern.test(command)) {
137
+ return { safe: false, error: `Command blocked: ${category}` };
138
+ }
139
+ }
140
+ // Check against dangerous pipe patterns
141
+ for (const { pattern, category } of DANGEROUS_PIPE_PATTERNS) {
142
+ if (pattern.test(command)) {
143
+ return { safe: false, error: `Command blocked: ${category}` };
144
+ }
145
+ }
146
+ return { safe: true };
147
+ }
148
+ //# sourceMappingURL=blocklist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocklist.js","sourceRoot":"","sources":["../../src/security/blocklist.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Session-level state for tracking archive metadata across tool calls.
3
+ *
4
+ * When extract_archive succeeds, we store the format and password used.
5
+ * When download_file runs with archive: true, we look up matching metadata
6
+ * to re-use the same format and password for the download archive.
7
+ */
8
+ export declare const DEFAULT_ARCHIVE_PASSWORD = "infected";
9
+ export declare const DEFAULT_ARCHIVE_FORMAT: "zip";
10
+ export interface ArchiveMetadata {
11
+ format: "zip" | "7z" | "rar";
12
+ password: string;
13
+ }
14
+ export declare class SessionState {
15
+ /**
16
+ * Maps sample filenames to the archive metadata from their extraction.
17
+ * Keys include both the archive filename and each extracted filename.
18
+ */
19
+ private archiveInfo;
20
+ /**
21
+ * Store archive metadata after a successful extraction.
22
+ *
23
+ * @param archiveFile - The archive filename (e.g., "sample.zip")
24
+ * @param extractedFiles - List of extracted filenames
25
+ * @param format - Archive format used
26
+ * @param password - Password that worked (empty string if none)
27
+ */
28
+ storeArchiveInfo(archiveFile: string, extractedFiles: string[], format: ArchiveMetadata["format"], password: string): void;
29
+ /**
30
+ * Look up archive metadata for a given filename.
31
+ * Returns undefined if no metadata was stored for this file.
32
+ */
33
+ getArchiveInfo(filename: string): ArchiveMetadata | undefined;
34
+ }
35
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/state/session.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,eAAO,MAAM,wBAAwB,aAAa,CAAC;AACnD,eAAO,MAAM,sBAAsB,EAAG,KAAc,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,YAAY;IACvB;;;OAGG;IACH,OAAO,CAAC,WAAW,CAAsC;IAEzD;;;;;;;OAOG;IACH,gBAAgB,CACd,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EAAE,EACxB,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,EACjC,QAAQ,EAAE,MAAM,GACf,IAAI;IAaP;;;OAGG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;CAG9D"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Session-level state for tracking archive metadata across tool calls.
3
+ *
4
+ * When extract_archive succeeds, we store the format and password used.
5
+ * When download_file runs with archive: true, we look up matching metadata
6
+ * to re-use the same format and password for the download archive.
7
+ */
8
+ import { basename } from "path";
9
+ export const DEFAULT_ARCHIVE_PASSWORD = "infected";
10
+ export const DEFAULT_ARCHIVE_FORMAT = "zip";
11
+ export class SessionState {
12
+ /**
13
+ * Maps sample filenames to the archive metadata from their extraction.
14
+ * Keys include both the archive filename and each extracted filename.
15
+ */
16
+ archiveInfo = new Map();
17
+ /**
18
+ * Store archive metadata after a successful extraction.
19
+ *
20
+ * @param archiveFile - The archive filename (e.g., "sample.zip")
21
+ * @param extractedFiles - List of extracted filenames
22
+ * @param format - Archive format used
23
+ * @param password - Password that worked (empty string if none)
24
+ */
25
+ storeArchiveInfo(archiveFile, extractedFiles, format, password) {
26
+ const meta = { format, password };
27
+ this.archiveInfo.set(archiveFile, meta);
28
+ for (const file of extractedFiles) {
29
+ this.archiveInfo.set(file, meta);
30
+ // Also store by basename so download_file can look up by basename(file_path)
31
+ const base = basename(file);
32
+ if (base !== file) {
33
+ this.archiveInfo.set(base, meta);
34
+ }
35
+ }
36
+ }
37
+ /**
38
+ * Look up archive metadata for a given filename.
39
+ * Returns undefined if no metadata was stored for this file.
40
+ */
41
+ getArchiveInfo(filename) {
42
+ return this.archiveInfo.get(filename);
43
+ }
44
+ }
45
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/state/session.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAEhC,MAAM,CAAC,MAAM,wBAAwB,GAAG,UAAU,CAAC;AACnD,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAc,CAAC;AAOrD,MAAM,OAAO,YAAY;IACvB;;;OAGG;IACK,WAAW,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEzD;;;;;;;OAOG;IACH,gBAAgB,CACd,WAAmB,EACnB,cAAwB,EACxB,MAAiC,EACjC,QAAgB;QAEhB,MAAM,IAAI,GAAoB,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QACnD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACxC,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;YAClC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACjC,6EAA6E;YAC7E,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,QAAgB;QAC7B,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;CACF"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Static tool definitions for all REMnux analysis tools.
3
+ *
4
+ * Each entry normalizes how a tool is invoked so the invoker doesn't need
5
+ * to know CLI quirks. Descriptions sourced from REMnux docs.
6
+ */
7
+ import type { ToolDefinition } from "./registry.js";
8
+ export declare const TOOL_DEFINITIONS: ToolDefinition[];
9
+ //# sourceMappingURL=definitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/tools/definitions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,eAAO,MAAM,gBAAgB,EAAE,cAAc,EA+sB5C,CAAC"}