paperclipai/paperclip · warning
UI parser path escapes package directory — skipping
Error message
UI parser path escapes package directory — skipping
What it means
Security guard in the plugin-loader: the ./ui-parser export path is resolved against the adapter package directory and must stay inside it (path prefix packageDir + path.sep). Absolute paths or ../ traversal that escape the package directory are rejected with this warning and the parser is skipped — preventing a malicious or misbuilt adapter from making the server read arbitrary files.
Source
Thrown at server/src/adapters/plugin-loader.ts:121
"Adapter declares unsupported UI parser contract version — skipping UI parser",
);
return undefined;
}
} else {
logger.info(
{ packageName },
"Adapter has ./ui-parser export but no paperclip.adapterUiParser version — loading anyway (future versions may require it)",
);
}
const uiParserExp = pkg.exports["./ui-parser"];
const uiParserFile = typeof uiParserExp === "string"
? uiParserExp
: (uiParserExp.import ?? uiParserExp.default);
const uiParserPath = path.resolve(packageDir, uiParserFile);
if (!uiParserPath.startsWith(packageDir + path.sep) && uiParserPath !== packageDir) {
logger.warn(
{ packageName, uiParserFile },
"UI parser path escapes package directory — skipping",
);
return undefined;
}
if (!fs.existsSync(uiParserPath)) {
return undefined;
}
try {
const source = fs.readFileSync(uiParserPath, "utf-8");
logger.info(
{ packageName, uiParserFile, size: source.length },
`Loaded UI parser from adapter package${contractVersion ? "" : " (no version declared)"}`,
);
return source;
} catch (err) {View on GitHub (pinned to a7e689b3c3)
Solutions
- Fix the adapter's package.json so ./ui-parser points to a file inside the package (e.g. "./dist/ui-parser.js").
- Rebuild/repack the adapter so the export target ships inside the package and the file exists there.
- If this comes from a third-party package you do not control, treat it as suspicious and audit before use.
Example fix
// adapter package.json — before
"exports": { "./ui-parser": "../../shared/ui-parser.js" }
// after
"exports": { "./ui-parser": "./dist/ui-parser.js" } Defensive patterns
Strategy: validation
Validate before calling
import path from 'node:path';
function isContainedExport(packageDir: string, exportPath: string): boolean {
if (path.isAbsolute(exportPath)) return false;
const resolved = path.resolve(packageDir, exportPath);
return resolved.startsWith(packageDir + path.sep);
}
// audit before loading a third-party adapter:
if (!isContainedExport(adapterDir, pkg.exports['./ui-parser'])) {
throw new Error(`Refusing adapter with escaping ui-parser export`);
} Prevention
- Install adapters only from trusted registries and audit their package.json exports.
- For in-house adapters, use bundler output paths under ./dist and add a lint rule enforcing it.
- Never bypass the loader's containment guard to 'make it work'.
- Treat this warn on a third-party package as a red flag, not an inconvenience.
When it happens
Trigger: An adapter's package.json exports["./ui-parser"] resolves outside the package directory — e.g. "../../shared/ui-parser.js", an absolute path, or a bundler emitting a wrong relative path during packaging.
Common situations: Hand-authored package.json exports; monorepo packaging tools rewriting relative paths; malicious third-party adapter probing for file reads.
Related errors
- Access denied
- Adapter declares unsupported UI parser contract version — sk
- sandbox runtime asset key is not a simple path segment: ${ke
- [plugin-kubernetes] egressMode=standard cannot enforce FQDN-
- ${prefix}: the capability must be an object.
AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-18).
Data as JSON: /api/errors/50feba258a81880f.
Report an issue: GitHub.