nexu-io/open-design · error · LocalDesignSystemImportError
BAD_REQUEST
BAD_REQUEST
Error message
repository contains symbolic links, which are not allowed
What it means
After a shallow git clone, the daemon scans the clone tree with containsSymlink. If any symbolic link exists, import is refused with BAD_REQUEST. The design-system readers and this importer follow symlinks, so a committed in-tree symlink pointing outside the clone (e.g. README.md -> /etc/passwd) would exfiltrate an arbitrary file into the imported design system.
Source
Thrown at apps/daemon/src/design-systems/github-import.ts:62
await mkdir(cloneRoot, { recursive: true });
const cloneDir = path.join(
cloneRoot,
`${parsed.owner}-${parsed.repo}-${importedAt.replace(/[^0-9a-z]/gi, '')}`,
);
const gitBin = options.gitBin ?? 'git';
const cloneArgs = ['clone', '--depth', '1'];
const branch = cleanBranch(options.branch);
if (branch) cloneArgs.push('--branch', branch);
cloneArgs.push(parsed.cloneUrl, cloneDir);
try {
await execGit(gitBin, cloneArgs, undefined, 120_000);
// Refuse a clone that contains symbolic links: the design-system readers and
// this importer follow symlinks, so a committed in-tree symlink pointing
// outside the clone (e.g. `README.md -> /etc/passwd`) would exfiltrate an
// arbitrary file into the imported design system. Mirrors installFromGithub.
if (await containsSymlink(cloneDir)) {
throw new LocalDesignSystemImportError(
'BAD_REQUEST',
'repository contains symbolic links, which are not allowed',
);
}
const [detectedBranch, commit] = await Promise.all([
readGitStdout(gitBin, ['-C', cloneDir, 'rev-parse', '--abbrev-ref', 'HEAD']),
readGitStdout(gitBin, ['-C', cloneDir, 'rev-parse', 'HEAD']),
]);
const sourceBranch = branch ?? normalizeDetachedBranch(detectedBranch);
return await importLocalDesignSystemProject(cloneDir, userDesignSystemsRoot, {
now: new Date(importedAt),
fallbackName: parsed.repo,
...(options.name ? { name: options.name } : {}),
...(options.reservedIds ? { reservedIds: options.reservedIds } : {}),
...(options.importMode ? { importMode: options.importMode } : {}),
...(options.craftApplies ? { craftApplies: options.craftApplies } : {}),
source: {
type: 'github',View on GitHub (pinned to 5be4028344)
Solutions
- Remove or resolve the symlinks in the source repository, then re-import.
- Import from a branch or tag that does not contain the symlinks.
- Fork the repo, replace symlinks with real files, and import the fork.
- Clone locally, clean the symlinks, and use the local import path instead.
Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
function isLocalDesignSystemImportError(err: unknown): err is LocalDesignSystemImportError {
return err instanceof Error && err.name === 'LocalDesignSystemImportError';
} Try / catch
try {
await importFromGithub(url, userRoot);
} catch (err) {
if (isLocalDesignSystemImportError(err) && err.code === 'BAD_REQUEST' && /symbolic links/i.test(err.message)) {
// tell the user the source repo has symlinks; suggest a cleaned fork or local import
} else throw err;
} Prevention
- Do not import repositories that commit symlinks; the guard exists to prevent file exfiltration.
- Fork the repo and replace symlinks with real files before importing.
- For repos you control, resolve symlinks at commit time so the tree is symlink-free.
When it happens
Trigger: The cloned GitHub repository contains at least one symbolic link in its tree. Detected after clone succeeds, before any design-system file is read.
Common situations: Monorepo tooling that commits symlinks; platform-specific symlink shims; adversarial repos deliberately planting escape symlinks; repos with symlinked config directories.
Related errors
- path escapes project dir
- project_files.read_json does not follow symlinks
- symlink_in_payload
- invalid brand id: ${input.brandId}
- invalid design system id: ${designSystemId}
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/3e3d9d2a04283d33.
Report an issue: GitHub.