{"record":{"id":"c473256aece9a1b9","repo":"CherryHQ/cherry-studio","slug":"agent-storage-path-contains-a-symbolic-link-cur","errorCode":null,"errorMessage":"Agent storage path contains a symbolic link: ${current}","messagePattern":"Agent storage path contains a symbolic link: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/main/ai/agents/agentDataDirectory.ts","lineNumber":64,"sourceCode":"  const root = asAbsolutePath(path.resolve(agentsDataRoot))\n  const target = asAbsolutePath(path.resolve(targetPath))\n  if (target !== root && !isPathInside(target, root)) {\n    throw new Error(`Agent storage path escapes its root: ${target}`)\n  }\n\n  const rootStat = await lstatIfExists(root)\n  if (!rootStat?.isDirectory || rootStat.isSymbolicLink) {\n    throw new Error(`Agent storage root must be a real directory: ${root}`)\n  }\n\n  let current = root\n  const relative = path.relative(root, target)\n  for (const segment of relative ? relative.split(path.sep) : []) {\n    current = asAbsolutePath(path.join(current, segment))\n    const currentStat = await lstatIfExists(current)\n    if (!currentStat) break\n    if (currentStat.isSymbolicLink) {\n      throw new Error(`Agent storage path contains a symbolic link: ${current}`)\n    }\n    if (current !== target && !currentStat.isDirectory) {\n      throw new Error(`Agent storage path parent is not a directory: ${current}`)\n    }\n  }\n\n  const [realRoot, realTarget] = await Promise.all([\n    resolveRealOrNearestExistingPath(root),\n    resolveRealOrNearestExistingPath(target)\n  ])\n  if (realTarget !== realRoot && !isPathInside(realTarget, realRoot)) {\n    throw new Error(`Agent storage path resolves outside its root: ${target}`)\n  }\n}\n\n/** Ensure a Data/Agents path is a real directory contained by the Agent storage root. */\nexport async function ensureAgentStorageDirectory(agentsDataRoot: string, targetPath: string): Promise<void> {\n  await ensureDir(asAbsolutePath(path.resolve(agentsDataRoot)))","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/agents/agentDataDirectory.ts#L46-L82","documentation":"Thrown by assertAgentStoragePath while walking each segment of the relative path from root to target: if any intermediate path component is a symbolic link (detected via lstat, which does not follow it), the walk aborts. This prevents a symlink planted inside the managed tree from redirecting a write outside the root (a classic TOCTOU/traversal escalation).","triggerScenarios":"A symlink exists anywhere along the path between Data/Agents and the target (e.g. Data/Agents/<agentId>/memory is a symlink to /tmp). A compromised or misconfigured agent data folder contains a link; a backup restore introduced links; an external tool created a symlinked subdirectory.","commonSituations":"User or another process created a symlink inside the agent data tree; a migration/sync tool preserved links; a malicious or buggy agent wrote a symlink; cross-platform sync (e.g. cloud drive) materialized links.","solutions":["Remove the offending symlink and replace it with a real directory/file as appropriate.","Investigate how the symlink got there — a recurring cause indicates a process (sync, backup, agent logic) recreating it.","Do not weaken the check to follow symlinks; the guard exists to prevent traversal escalation.","Run a filesystem audit for symlinks under Data/Agents: find <agentsDataRoot> -type l."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { lstatIfExists } from './agentDataDirectory'\n// Walk root..target and reject any symlink segment\nfor (const seg of path.relative(root, target).split(path.sep)) {\n  current = path.join(current, seg)\n  const st = await lstatIfExists(current)\n  if (st?.isSymbolicLink) throw new Error(`Refusing: '${current}' is a symlink inside agents root`)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not place symlinks inside the Data/Agents tree.","Periodically audit for symlinks under the agents root (find <root> -type l).","Investigate any tool (sync/backup/agent logic) that recreates links inside the data folder."],"tags":["security","filesystem","symlink","path-traversal","agent"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}