@herdctl/core 2.1.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/config/__tests__/agent.test.js +67 -48
  2. package/dist/config/__tests__/agent.test.js.map +1 -1
  3. package/dist/config/__tests__/loader.test.js +22 -26
  4. package/dist/config/__tests__/loader.test.js.map +1 -1
  5. package/dist/config/__tests__/merge.test.js +32 -77
  6. package/dist/config/__tests__/merge.test.js.map +1 -1
  7. package/dist/config/__tests__/parser.test.js +30 -48
  8. package/dist/config/__tests__/parser.test.js.map +1 -1
  9. package/dist/config/__tests__/schema.test.js +8 -36
  10. package/dist/config/__tests__/schema.test.js.map +1 -1
  11. package/dist/config/index.d.ts +2 -2
  12. package/dist/config/index.d.ts.map +1 -1
  13. package/dist/config/index.js +1 -1
  14. package/dist/config/index.js.map +1 -1
  15. package/dist/config/merge.d.ts +8 -14
  16. package/dist/config/merge.d.ts.map +1 -1
  17. package/dist/config/merge.js +11 -6
  18. package/dist/config/merge.js.map +1 -1
  19. package/dist/config/schema.d.ts +91 -271
  20. package/dist/config/schema.d.ts.map +1 -1
  21. package/dist/config/schema.js +13 -13
  22. package/dist/config/schema.js.map +1 -1
  23. package/dist/runner/__tests__/sdk-adapter.test.js +25 -159
  24. package/dist/runner/__tests__/sdk-adapter.test.js.map +1 -1
  25. package/dist/runner/runtime/cli-runtime.d.ts.map +1 -1
  26. package/dist/runner/runtime/cli-runtime.js +6 -28
  27. package/dist/runner/runtime/cli-runtime.js.map +1 -1
  28. package/dist/runner/runtime/container-manager.d.ts.map +1 -1
  29. package/dist/runner/runtime/container-manager.js +9 -1
  30. package/dist/runner/runtime/container-manager.js.map +1 -1
  31. package/dist/runner/sdk-adapter.d.ts.map +1 -1
  32. package/dist/runner/sdk-adapter.js +7 -21
  33. package/dist/runner/sdk-adapter.js.map +1 -1
  34. package/dist/state/job-metadata.d.ts.map +1 -1
  35. package/dist/state/job-metadata.js +6 -1
  36. package/dist/state/job-metadata.js.map +1 -1
  37. package/dist/state/session.d.ts.map +1 -1
  38. package/dist/state/session.js +6 -2
  39. package/dist/state/session.js.map +1 -1
  40. package/dist/state/utils/__tests__/path-safety.test.d.ts +2 -0
  41. package/dist/state/utils/__tests__/path-safety.test.d.ts.map +1 -0
  42. package/dist/state/utils/__tests__/path-safety.test.js +182 -0
  43. package/dist/state/utils/__tests__/path-safety.test.js.map +1 -0
  44. package/dist/state/utils/index.d.ts +1 -0
  45. package/dist/state/utils/index.d.ts.map +1 -1
  46. package/dist/state/utils/index.js +1 -0
  47. package/dist/state/utils/index.js.map +1 -1
  48. package/dist/state/utils/path-safety.d.ts +51 -0
  49. package/dist/state/utils/path-safety.d.ts.map +1 -0
  50. package/dist/state/utils/path-safety.js +75 -0
  51. package/dist/state/utils/path-safety.js.map +1 -0
  52. package/package.json +2 -2
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Path safety utilities for state file operations
3
+ *
4
+ * Provides defense-in-depth protection against path traversal attacks
5
+ * when constructing file paths from user-controlled identifiers.
6
+ */
7
+ /**
8
+ * Error thrown when a path traversal attempt is detected
9
+ */
10
+ export declare class PathTraversalError extends Error {
11
+ readonly baseDir: string;
12
+ readonly identifier: string;
13
+ readonly resultPath: string;
14
+ constructor(baseDir: string, identifier: string, resultPath: string);
15
+ }
16
+ /**
17
+ * Pattern for valid identifiers (agent names, etc.)
18
+ * Must start with alphanumeric, can contain alphanumeric, underscore, hyphen
19
+ */
20
+ export declare const SAFE_IDENTIFIER_PATTERN: RegExp;
21
+ /**
22
+ * Validate that an identifier is safe for use in file paths
23
+ *
24
+ * @param identifier - The identifier to validate (agent name, etc.)
25
+ * @returns true if valid, false if not
26
+ */
27
+ export declare function isValidIdentifier(identifier: string): boolean;
28
+ /**
29
+ * Build a safe file path within a base directory
30
+ *
31
+ * This function provides defense-in-depth by:
32
+ * 1. Checking the identifier against a safe pattern
33
+ * 2. Resolving the final path and verifying it stays within the base directory
34
+ *
35
+ * @param baseDir - The base directory that the file must stay within
36
+ * @param identifier - The user-provided identifier (agent name, etc.)
37
+ * @param extension - File extension including the dot (e.g., ".json", ".yaml")
38
+ * @returns The safe, resolved file path
39
+ * @throws PathTraversalError if the path would escape the base directory
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const filePath = buildSafeFilePath("/home/user/.herdctl/sessions", "my-agent", ".json");
44
+ * // Returns: "/home/user/.herdctl/sessions/my-agent.json"
45
+ *
46
+ * // This would throw PathTraversalError:
47
+ * buildSafeFilePath("/home/user/.herdctl/sessions", "../../../etc/passwd", ".json");
48
+ * ```
49
+ */
50
+ export declare function buildSafeFilePath(baseDir: string, identifier: string, extension: string): string;
51
+ //# sourceMappingURL=path-safety.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-safety.d.ts","sourceRoot":"","sources":["../../../src/state/utils/path-safety.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,SAAgB,OAAO,EAAE,MAAM,CAAC;IAChC,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,UAAU,EAAE,MAAM,CAAC;gBAEvB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CASpE;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,QAAgC,CAAC;AAErE;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,MAAM,CAuBR"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Path safety utilities for state file operations
3
+ *
4
+ * Provides defense-in-depth protection against path traversal attacks
5
+ * when constructing file paths from user-controlled identifiers.
6
+ */
7
+ import { resolve, join } from "node:path";
8
+ /**
9
+ * Error thrown when a path traversal attempt is detected
10
+ */
11
+ export class PathTraversalError extends Error {
12
+ baseDir;
13
+ identifier;
14
+ resultPath;
15
+ constructor(baseDir, identifier, resultPath) {
16
+ super(`Path traversal detected: identifier "${identifier}" would resolve to "${resultPath}" which is outside base directory "${baseDir}"`);
17
+ this.name = "PathTraversalError";
18
+ this.baseDir = baseDir;
19
+ this.identifier = identifier;
20
+ this.resultPath = resultPath;
21
+ }
22
+ }
23
+ /**
24
+ * Pattern for valid identifiers (agent names, etc.)
25
+ * Must start with alphanumeric, can contain alphanumeric, underscore, hyphen
26
+ */
27
+ export const SAFE_IDENTIFIER_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
28
+ /**
29
+ * Validate that an identifier is safe for use in file paths
30
+ *
31
+ * @param identifier - The identifier to validate (agent name, etc.)
32
+ * @returns true if valid, false if not
33
+ */
34
+ export function isValidIdentifier(identifier) {
35
+ return SAFE_IDENTIFIER_PATTERN.test(identifier);
36
+ }
37
+ /**
38
+ * Build a safe file path within a base directory
39
+ *
40
+ * This function provides defense-in-depth by:
41
+ * 1. Checking the identifier against a safe pattern
42
+ * 2. Resolving the final path and verifying it stays within the base directory
43
+ *
44
+ * @param baseDir - The base directory that the file must stay within
45
+ * @param identifier - The user-provided identifier (agent name, etc.)
46
+ * @param extension - File extension including the dot (e.g., ".json", ".yaml")
47
+ * @returns The safe, resolved file path
48
+ * @throws PathTraversalError if the path would escape the base directory
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const filePath = buildSafeFilePath("/home/user/.herdctl/sessions", "my-agent", ".json");
53
+ * // Returns: "/home/user/.herdctl/sessions/my-agent.json"
54
+ *
55
+ * // This would throw PathTraversalError:
56
+ * buildSafeFilePath("/home/user/.herdctl/sessions", "../../../etc/passwd", ".json");
57
+ * ```
58
+ */
59
+ export function buildSafeFilePath(baseDir, identifier, extension) {
60
+ // First line of defense: validate identifier format
61
+ if (!isValidIdentifier(identifier)) {
62
+ throw new PathTraversalError(baseDir, identifier, `(invalid identifier: must match ${SAFE_IDENTIFIER_PATTERN})`);
63
+ }
64
+ // Construct the file path
65
+ const fileName = `${identifier}${extension}`;
66
+ const filePath = join(baseDir, fileName);
67
+ // Second line of defense: verify the resolved path stays within baseDir
68
+ const resolvedBase = resolve(baseDir);
69
+ const resolvedPath = resolve(filePath);
70
+ if (!resolvedPath.startsWith(resolvedBase + "/") && resolvedPath !== resolvedBase) {
71
+ throw new PathTraversalError(baseDir, identifier, resolvedPath);
72
+ }
73
+ return filePath;
74
+ }
75
+ //# sourceMappingURL=path-safety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-safety.js","sourceRoot":"","sources":["../../../src/state/utils/path-safety.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C;;GAEG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3B,OAAO,CAAS;IAChB,UAAU,CAAS;IACnB,UAAU,CAAS;IAEnC,YAAY,OAAe,EAAE,UAAkB,EAAE,UAAkB;QACjE,KAAK,CACH,wCAAwC,UAAU,uBAAuB,UAAU,sCAAsC,OAAO,GAAG,CACpI,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,6BAA6B,CAAC;AAErE;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,OAAO,uBAAuB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAClD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAe,EACf,UAAkB,EAClB,SAAiB;IAEjB,oDAAoD;IACpD,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,kBAAkB,CAC1B,OAAO,EACP,UAAU,EACV,mCAAmC,uBAAuB,GAAG,CAC9D,CAAC;IACJ,CAAC;IAED,0BAA0B;IAC1B,MAAM,QAAQ,GAAG,GAAG,UAAU,GAAG,SAAS,EAAE,CAAC;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAEzC,wEAAwE;IACxE,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEvC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,YAAY,GAAG,GAAG,CAAC,IAAI,YAAY,KAAK,YAAY,EAAE,CAAC;QAClF,MAAM,IAAI,kBAAkB,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@herdctl/core",
3
- "version": "2.1.0",
3
+ "version": "3.0.1",
4
4
  "description": "Core library for herdctl fleet management",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -20,7 +20,7 @@
20
20
  "zod": "^3.22.0"
21
21
  },
22
22
  "peerDependencies": {
23
- "@herdctl/discord": "0.1.7"
23
+ "@herdctl/discord": "0.1.9"
24
24
  },
25
25
  "peerDependenciesMeta": {
26
26
  "@herdctl/discord": {