{"record":{"id":"67952733553aae5a","repo":"stablyai/orca","slug":"managed-claude-auth-child-file-is-not-owned-by-orc","errorCode":null,"errorMessage":"Managed Claude auth child file is not owned by Orca.","messagePattern":"Managed Claude auth child file is not owned by Orca\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/claude-accounts/managed-auth-path.ts","lineNumber":81,"sourceCode":"  const filePath = resolve(managedAuthPath, filename)\n  try {\n    if (!isOwnedChildFile(managedAuthPath, filePath)) {\n      return null\n    }\n    return readFileSync(filePath, 'utf-8')\n  } catch {\n    return null\n  }\n}\n\nexport function writeClaudeManagedAuthFile(\n  managedAuthPath: string,\n  filename: '.credentials.json' | 'oauth-account.json',\n  contents: string\n): void {\n  const filePath = resolve(managedAuthPath, filename)\n  if (existsSync(filePath) && !isOwnedChildFile(managedAuthPath, filePath)) {\n    throw new Error('Managed Claude auth child file is not owned by Orca.')\n  }\n  writeFileAtomically(filePath, contents, { mode: 0o600 })\n}\n\nfunction isManagedAuthMarkerValid(markerPath: string, accountId: string): boolean {\n  try {\n    if (\n      !existsSync(markerPath) ||\n      lstatSync(markerPath).isSymbolicLink() ||\n      !lstatSync(markerPath).isFile()\n    ) {\n      return false\n    }\n    return readFileSync(markerPath, 'utf-8').trim() === accountId\n  } catch {\n    return false\n  }\n}","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/claude-accounts/managed-auth-path.ts#L63-L99","documentation":"Thrown by writeClaudeManagedAuthFile() when the target child file (.credentials.json or oauth-account.json) exists but isOwnedChildFile() returns false — i.e. the file's canonical path (realpath) does not lie under the managed auth directory, or it is a symlink, or it is not a regular file. This is a path-traversal / ownership guard: Orca only overwrites files it created inside its own managed account directory.","triggerScenarios":"The target file path resolves (via symlink) outside the managedAuthPath. A pre-existing .credentials.json was created by an unrelated process. Someone replaced the file with a symlink. The managed directory was moved/relabeled so realpath no longer matches.","commonSituations":"User manually placed a .credentials.json in the managed dir. A symlink attack or misconfigured managedAuthPath pointing at a shared location. Stale account directory after a userData migration changed canonical paths.","solutions":["Remove the offending file/symlink and let Orca recreate it: delete the child file then re-run the auth write.","Confirm managedAuthPath resolves under app.getPath('userData')/claude-accounts and was created via resolveOwnedClaudeManagedAuthPath.","Audit for symlinks in the account auth directory (lstat) and reject/repair before write.","Re-add the Claude account so Orca recreates a clean owned directory."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { existsSync, lstatSync } from 'node:fs'\n\nfunction isSafeOwnedChild(parentDir: string, file: string): boolean {\n  if (!existsSync(file)) return true // new file is fine\n  const stat = lstatSync(file)\n  return stat.isFile() && !stat.isSymbolicLink()\n}","typeGuard":null,"tryCatchPattern":"try {\n  writeClaudeManagedAuthFile(managedAuthPath, '.credentials.json', contents)\n} catch (error) {\n  if (error instanceof Error && /not owned by Orca/.test(error.message)) {\n    // Recreate the account directory or remove the offending file\n    throw new Error('Auth file is foreign; re-add the account.')\n  }\n  throw error\n}","preventionTips":["Only write into paths resolved by resolveOwnedClaudeManagedAuthPath.","Never symlink inside the managed auth directory.","Recreate account directories via the add flow rather than manual file placement.","Audit for symlinks before write."],"tags":["security","path-traversal","symlink","managed-auth","claude-accounts"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}