paperclipai/paperclip · error · Error
Plugin migrationsDir escapes package root: ${migrationsDir}
Error message
Plugin migrationsDir escapes package root: ${migrationsDir} What it means
Path-traversal guard in resolveMigrationsDir: after joining and resolving, the plugin's configured migrationsDir resolves outside the plugin package root. A malicious or misconfigured manifest could otherwise point migrations at arbitrary host directories; the escaping migrationsDir value is at fault.
Source
Thrown at server/src/services/plugin-database.ts:341
throw new Error("Every ctx.db parameter must be referenced by a $n placeholder");
}
return sql.join(chunks, sql.raw(""));
}
async function listSqlMigrationFiles(migrationsDir: string): Promise<string[]> {
const entries = await readdir(migrationsDir, { withFileTypes: true });
return entries
.filter((entry) => entry.isFile() && entry.name.endsWith(".sql"))
.map((entry) => entry.name)
.sort((a, b) => a.localeCompare(b));
}
function resolveMigrationsDir(packageRoot: string, migrationsDir: string): string {
const resolvedRoot = path.resolve(packageRoot);
const resolvedDir = path.resolve(resolvedRoot, migrationsDir);
const relative = path.relative(resolvedRoot, resolvedDir);
if (relative.startsWith("..") || path.isAbsolute(relative)) {
throw new Error(`Plugin migrationsDir escapes package root: ${migrationsDir}`);
}
return resolvedDir;
}
type PluginDatabaseClient = Pick<Db, "select" | "insert" | "update" | "execute">;
type PluginDatabaseRootClient = PluginDatabaseClient & Partial<Pick<Db, "transaction">>;
export interface ApplyPluginMigrationsOptions {
/**
* Persist failed migration ledger rows. Fresh install uses false because the
* caller owns a larger transaction and must roll back the plugin row and
* namespace together.
*/
persistFailure?: boolean;
}
export function pluginDatabaseService(db: PluginDatabaseRootClient) {
async function getPluginRecord(pluginId: string) {View on GitHub (pinned to 120ae5428f)
Solutions
- Set migrationsDir to a path inside the plugin package root.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at server/src/services/plugin-database.ts:341 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of paperclipai/paperclip@120ae5428f (2026-08-18).
Data as JSON: /api/errors/b55626915b274be3.
Report an issue: GitHub.