@task-mcp/shared 1.0.21 → 1.0.23

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.
@@ -7,12 +7,18 @@
7
7
  * 3. Current working directory basename (final fallback)
8
8
  */
9
9
 
10
- import { exec } from "node:child_process";
10
+ import { exec, execSync } from "node:child_process";
11
11
  import { promisify } from "node:util";
12
12
  import { basename } from "node:path";
13
13
 
14
14
  const execAsync = promisify(exec);
15
15
 
16
+ /**
17
+ * Maximum length for workspace names.
18
+ * Prevents excessive path lengths and potential DoS via long names.
19
+ */
20
+ const MAX_WORKSPACE_LENGTH = 64;
21
+
16
22
  /**
17
23
  * Normalize a string to a valid workspace name.
18
24
  *
@@ -21,6 +27,7 @@ const execAsync = promisify(exec);
21
27
  * - Replace spaces with hyphens
22
28
  * - Keep alphanumeric, hyphens, and underscores
23
29
  * - Trim leading/trailing hyphens
30
+ * - Limit to MAX_WORKSPACE_LENGTH characters
24
31
  *
25
32
  * @param name - Raw name to normalize
26
33
  * @returns Normalized workspace name
@@ -29,15 +36,19 @@ const execAsync = promisify(exec);
29
36
  * ```typescript
30
37
  * normalizeWorkspace('My Project'); // 'my-project'
31
38
  * normalizeWorkspace('Task-MCP'); // 'task-mcp'
39
+ * normalizeWorkspace('a'.repeat(100)); // 64 chars max
32
40
  * ```
33
41
  */
34
42
  export function normalizeWorkspace(name: string): string {
35
- return name
43
+ const normalized = name
36
44
  .toLowerCase()
37
45
  .replace(/\s+/g, "-")
38
46
  .replace(/[^a-z0-9_-]/g, "")
39
47
  .replace(/^-+|-+$/g, "")
40
- || "default";
48
+ .slice(0, MAX_WORKSPACE_LENGTH) // Enforce length limit
49
+ .replace(/-+$/, ""); // Clean trailing hyphens after truncation
50
+
51
+ return normalized || "default";
41
52
  }
42
53
 
43
54
  /**
@@ -66,11 +77,12 @@ export async function getGitRepoRoot(cwd?: string): Promise<string | null> {
66
77
  */
67
78
  export function getGitRepoRootSync(cwd?: string): string | null {
68
79
  try {
69
- const { execSync } = require("node:child_process");
70
80
  const result = execSync("git rev-parse --show-toplevel", {
71
81
  cwd: cwd ?? process.cwd(),
72
82
  encoding: "utf-8",
73
83
  stdio: ["pipe", "pipe", "pipe"],
84
+ timeout: 5000, // 5 second timeout
85
+ maxBuffer: 1024, // Limit output buffer
74
86
  });
75
87
  return (result as string).trim() || null;
76
88
  } catch {