{"record":{"id":"5264daa662f60847","repo":"coleam00/Archon","slug":"path-must-be-within-workspaceroot-directory","errorCode":null,"errorMessage":"Path must be within ${workspaceRoot} directory","messagePattern":"Path must be within (.+?) directory","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/utils/path-validation.ts","lineNumber":42,"sourceCode":"  return resolvedTarget === workspaceRoot || resolvedTarget.startsWith(workspaceRoot + sep);\n}\n\n/**\n * Validates a path and returns the resolved absolute path if valid.\n * Throws an error if the path escapes the workspace.\n *\n * @param targetPath - The path to validate\n * @param basePath - Optional base path to resolve relative paths against\n * @returns The resolved absolute path\n * @throws Error if path is outside workspace\n */\nexport function validateAndResolvePath(targetPath: string, basePath?: string): string {\n  const workspaceRoot = getWorkspaceRoot();\n  const effectiveBase = basePath ?? workspaceRoot;\n  const resolvedPath = resolve(effectiveBase, targetPath);\n\n  if (!isPathWithinWorkspace(resolvedPath)) {\n    throw new Error(`Path must be within ${workspaceRoot} directory`);\n  }\n\n  return resolvedPath;\n}\n","sourceCodeStart":24,"sourceCodeEnd":47,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/core/src/utils/path-validation.ts#L24-L47","documentation":"validateAndResolvePath resolves a target path against a base (defaults to the Archon workspace root) and throws if the resolved path escapes that root. It is the central path-traversal guard ensuring all file operations stay inside the workspace. The message names the workspace root that was violated.","triggerScenarios":"Calling validateAndResolvePath with a path containing '..' or an absolute path outside the workspace, or passing a basePath whose resolution combined with targetPath lands outside the workspace root when isPathWithinWorkspace is checked.","commonSituations":"User-supplied file paths in workflow inputs reaching file APIs; symlinks or '..' segments in artifact paths; passing an absolute path from outside the Archon workspace (e.g. /etc/passwd or a project dir elsewhere on disk).","solutions":["Pass a path relative to the workspace root (or within it) instead of an absolute outside path.","If you intend to operate on an outside directory, register it as a codebase or use the appropriate API rather than raw path access.","Supply a basePath that already sits inside the workspace so the resolution stays within it.","Check for symlinks in the workspace that resolve outside the root and remove/re-point them."],"exampleFix":"// before\nvalidateAndResolvePath('/etc/hosts');\n// after\nvalidateAndResolvePath('runs/123/artifacts/output.json');","handlingStrategy":"validation","validationCode":"import { isAbsolute, resolve } from 'node:path';\nfunction assertWorkspaceRelative(p: string) {\n  if (isAbsolute(p) || p.split(/[\\\\/]/).includes('..')) {\n    throw new Error(`path must be workspace-relative: ${p}`);\n  }\n}\nassertWorkspaceRelative(userPath); // then call validateAndResolvePath(userPath)","typeGuard":"function isWithin(root: string, target: string): boolean {\n  const rel = relative(root, target);\n  return rel !== '' && !rel.startsWith('..') && !isAbsolute(rel);\n}","tryCatchPattern":"try {\n  const p = validateAndResolvePath(input);\n} catch (e) {\n  if (e.message.includes('Path must be within')) {\n    console.error('Reject the input path; it escapes the workspace root');\n  } else throw e;\n}","preventionTips":["Treat all user-supplied paths as untrusted; pass them through validateAndResolvePath first.","Use workspace-relative paths in workflow inputs and artifacts.","Audit for symlinks in the workspace that point outside the root."],"tags":["path","validation","security","traversal"],"backgroundTag":"path-traversal-blocked","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}