{"record":{"id":"31d0952799f7555b","repo":"paperclipai/paperclip","slug":"refusing-to-use-unsafe-install-store-marker-path","errorCode":null,"errorMessage":"Refusing to use unsafe install-store marker ${paths.markerPath}.","messagePattern":"Refusing to use unsafe install-store marker (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"cli/src/install-store.ts","lineNumber":95,"sourceCode":"  return {\n    paperclipHome,\n    cliRoot,\n    installsRoot: path.join(cliRoot, \"installs\"),\n    manifestPath: path.join(cliRoot, \"install.json\"),\n    markerPath: path.join(cliRoot, \".managed-install\"),\n    lockPath: path.join(cliRoot, \".install.lock\"),\n    currentPath: path.join(cliRoot, \"current\"),\n    shimPath: path.join(homeDir, \".local\", \"bin\", \"paperclipai\"),\n  };\n}\n\nexport function initializeInstallStore(paths = resolveInstallStorePaths()): void {\n  ensurePrivateDirectory(paths.cliRoot);\n  ensurePrivateDirectory(paths.installsRoot);\n  try {\n    const markerStat = fs.lstatSync(paths.markerPath);\n    if (!markerStat.isFile() || markerStat.isSymbolicLink() || markerStat.nlink > 1) {\n      throw new Error(`Refusing to use unsafe install-store marker ${paths.markerPath}.`);\n    }\n    assertOwnedByCurrentUser(markerStat, paths.markerPath);\n    if (fs.readFileSync(paths.markerPath, \"utf8\") !== MANAGED_STORE_MARKER) {\n      throw new Error(`Refusing to use unrecognized install store ${paths.cliRoot}.`);\n    }\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n    try {\n      fs.writeFileSync(paths.markerPath, MANAGED_STORE_MARKER, { mode: 0o600, flag: \"wx\" });\n    } catch (writeError) {\n      if (\n        (writeError as NodeJS.ErrnoException).code !== \"EEXIST\" ||\n        fs.readFileSync(paths.markerPath, \"utf8\") !== MANAGED_STORE_MARKER\n      ) {\n        throw writeError;\n      }\n    }\n  }","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/install-store.ts#L77-L113","documentation":"Thrown by initializeInstallStore() when the managed-install marker file (.managed-install) exists but is not a regular file — it is a symlink (isSymbolicLink) or has multiple hard links (nlink > 1). The marker file must be a unique regular file owned by the current user because its contents authenticate the store as genuinely Paperclip-managed; a symlinked or hardlinked marker could be spoofed.","triggerScenarios":"Called initializeInstallStore() (directly or via withInstallStoreLock) where paths.markerPath exists and lstatSync reports it as a symlink or as a file with nlink > 1.","commonSituations":"1) An attacker or misconfigured tool replaced ~/.paperclip/cli/.managed-install with a symlink to a marker file elsewhere. 2) A hard link was created to the marker from another location. 3) A backup/sync tool (rsync with --links) recreated the marker as a symlink.","solutions":["Remove the offending marker entry: 'rm ~/.paperclip/cli/.managed-install' and let initializeInstallStore recreate it as a fresh regular file with mode 0o600.","Confirm no symlink or hardlink was intentionally placed — if unexpected, audit for tampering.","Re-run 'paperclipai install' after cleanup so the marker is written correctly."],"exampleFix":"$ ls -la ~/.paperclip/cli/.managed-install\nlrwxrwxrwx  .managed-install -> /tmp/fake-marker\n$ rm ~/.paperclip/cli/.managed-install\n$ paperclipai install   # recreates marker as regular file","handlingStrategy":"validation","validationCode":"import fs from \"node:fs\";\nimport { resolveInstallStorePaths, MANAGED_STORE_MARKER } from \"./install-store.js\";\n\nfunction isSafeMarker(paths = resolveInstallStorePaths()): boolean {\n  try {\n    const st = fs.lstatSync(paths.markerPath);\n    return st.isFile() && !st.isSymbolicLink() && st.nlink === 1;\n  } catch { return false; }\n}","typeGuard":"import fs from \"node:fs\";\n\nfunction isRegularUnlinkedFile(p: string): boolean {\n  const st = fs.lstatSync(p);\n  return st.isFile() && !st.isSymbolicLink() && st.nlink === 1;\n}","tryCatchPattern":"try {\n  initializeInstallStore(paths);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"unsafe install-store marker\")) {\n    fs.rmSync(paths.markerPath, { force: true });\n    initializeInstallStore(paths); // recreate\n  } else throw err;\n}","preventionTips":["Never symlink or hardlink the .managed-install marker.","Use rsync without --links when backing up the store, or exclude the marker.","Audit marker type after any restore.","Do not hand-edit the marker file."],"tags":["install-store","security","marker","symlink-guard","cli"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}