paperclipai/paperclip · critical · Error
Refusing to use unsafe install-store marker ${paths.markerPa
Error message
Refusing to use unsafe install-store marker ${paths.markerPath}. What it means
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.
Source
Thrown at cli/src/install-store.ts:95
return {
paperclipHome,
cliRoot,
installsRoot: path.join(cliRoot, "installs"),
manifestPath: path.join(cliRoot, "install.json"),
markerPath: path.join(cliRoot, ".managed-install"),
lockPath: path.join(cliRoot, ".install.lock"),
currentPath: path.join(cliRoot, "current"),
shimPath: path.join(homeDir, ".local", "bin", "paperclipai"),
};
}
export function initializeInstallStore(paths = resolveInstallStorePaths()): void {
ensurePrivateDirectory(paths.cliRoot);
ensurePrivateDirectory(paths.installsRoot);
try {
const markerStat = fs.lstatSync(paths.markerPath);
if (!markerStat.isFile() || markerStat.isSymbolicLink() || markerStat.nlink > 1) {
throw new Error(`Refusing to use unsafe install-store marker ${paths.markerPath}.`);
}
assertOwnedByCurrentUser(markerStat, paths.markerPath);
if (fs.readFileSync(paths.markerPath, "utf8") !== MANAGED_STORE_MARKER) {
throw new Error(`Refusing to use unrecognized install store ${paths.cliRoot}.`);
}
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
try {
fs.writeFileSync(paths.markerPath, MANAGED_STORE_MARKER, { mode: 0o600, flag: "wx" });
} catch (writeError) {
if (
(writeError as NodeJS.ErrnoException).code !== "EEXIST" ||
fs.readFileSync(paths.markerPath, "utf8") !== MANAGED_STORE_MARKER
) {
throw writeError;
}
}
}View on GitHub (pinned to 67001ec6eb)
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.
Example fix
$ ls -la ~/.paperclip/cli/.managed-install lrwxrwxrwx .managed-install -> /tmp/fake-marker $ rm ~/.paperclip/cli/.managed-install $ paperclipai install # recreates marker as regular file
Defensive patterns
Strategy: validation
Validate before calling
import fs from "node:fs";
import { resolveInstallStorePaths, MANAGED_STORE_MARKER } from "./install-store.js";
function isSafeMarker(paths = resolveInstallStorePaths()): boolean {
try {
const st = fs.lstatSync(paths.markerPath);
return st.isFile() && !st.isSymbolicLink() && st.nlink === 1;
} catch { return false; }
} Type guard
import fs from "node:fs";
function isRegularUnlinkedFile(p: string): boolean {
const st = fs.lstatSync(p);
return st.isFile() && !st.isSymbolicLink() && st.nlink === 1;
} Try / catch
try {
initializeInstallStore(paths);
} catch (err) {
if (err instanceof Error && err.message.includes("unsafe install-store marker")) {
fs.rmSync(paths.markerPath, { force: true });
initializeInstallStore(paths); // recreate
} else throw err;
} Prevention
- 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.
When it happens
Trigger: Called initializeInstallStore() (directly or via withInstallStoreLock) where paths.markerPath exists and lstatSync reports it as a symlink or as a file with nlink > 1.
Common situations: 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.
Related errors
- Refusing to use non-directory install-store path ${directory
- Refusing to use unrecognized install store ${paths.cliRoot}.
- Refusing to remove unsafe install-store path ${paths.cliRoot
- Refusing to remove unverified install store ${paths.cliRoot}
- Refusing to activate payload outside ${paths.installsRoot}.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/31d0952799f7555b.
Report an issue: GitHub.