mihomo-party-org/clash-party · error
Invalid core path: directory traversal detected
Error message
Invalid core path: directory traversal detected
What it means
validateCorePath is a security guard for paths that will be handed to permission-granting commands (e.g. setuid/chmod for TUN). It rejects any core path containing '..' to prevent directory-traversal attacks where a caller could elevate or overwrite an unintended binary. The check is intentionally blunt: any '..' substring anywhere in the path throws immediately.
Source
Thrown at src/main/core/permissions.ts:34
// 内核名称白名单
const ALLOWED_CORES = ['mihomo', 'mihomo-alpha', 'mihomo-smart'] as const
type AllowedCore = (typeof ALLOWED_CORES)[number]
type StopCoreBeforeAdminRestart = (force?: boolean) => Promise<void>
let stopCoreBeforeAdminRestart: StopCoreBeforeAdminRestart | null = null
export function setStopCoreBeforeAdminRestart(stopCore: StopCoreBeforeAdminRestart): void {
stopCoreBeforeAdminRestart = stopCore
}
export function isValidCoreName(core: string): core is AllowedCore {
return ALLOWED_CORES.includes(core as AllowedCore)
}
export function validateCorePath(corePath: string): void {
if (corePath.includes('..')) {
throw new Error('Invalid core path: directory traversal detected')
}
const dangerousChars = /[;&|`$(){}[\]<>'"\\]/
if (dangerousChars.test(path.basename(corePath))) {
throw new Error('Invalid core path: contains dangerous characters')
}
const normalizedPath = path.normalize(path.resolve(corePath))
const expectedDir = path.normalize(path.resolve(mihomoCoreDir()))
if (!normalizedPath.startsWith(expectedDir + path.sep) && normalizedPath !== expectedDir) {
throw new Error('Invalid core path: not in expected directory')
}
}
function shellEscape(arg: string): string {
return "'" + arg.replace(/'/g, "'\\''") + "'"
}View on GitHub (pinned to 911e090537)
Solutions
- Pass an absolute, normalized path (path.resolve) to grantTunPermissions so no '..' segment remains.
- Fix the user's custom core path setting to point directly at the binary (e.g. /opt/mihomo/mihomo).
- If building paths programmatically, use path.join/path.resolve rather than string concatenation.
- Reinstall the core to the app-managed location and clear the custom path override.
Example fix
// before
await grantTunPermissions('../opt/mihomo/mihomo')
// after
const corePath = path.resolve('/opt/mihomo/mihomo')
if (corePath.includes('..')) throw new Error('bad core path')
await grantTunPermissions(corePath) Defensive patterns
Strategy: validation
Validate before calling
import path from 'path'
function safeCorePath(input: string): string {
const resolved = path.resolve(input)
if (input.includes('..')) throw new Error('Directory traversal detected in core path')
if (!path.isAbsolute(resolved)) throw new Error('Core path must be absolute')
return resolved
}
// usage: await grantTunPermissions(safeCorePath(userCorePath)) Type guard
function isSafeCorePath(p: string): boolean {
return path.isAbsolute(p) && !p.includes('..') && path.basename(p).length > 0
} Try / catch
try {
validateCorePath(corePath)
await grantTunPermissions(corePath)
} catch (e) {
if (String((e as Error).message).includes('traversal')) {
throw new Error(`Refusing unsafe core path "${corePath}"; use an absolute path without '..'`)
}
throw e
} Prevention
- Always pass absolute paths built with path.resolve, never string-concatenated relative segments.
- Restrict custom core paths to known install directories.
- Treat any user-supplied path as untrusted and run the validator before any privileged operation.
When it happens
Trigger: Calling grantTunPermissions with a corePath containing '..' — e.g. a user-configured core path like '../opt/mihomo/mihomo' or a path built by naive string concatenation of a relative user setting with a base directory.
Common situations: Users typing relative paths in custom core-path settings; config migration producing '../../usr/bin/mihomo'; scripts/automation building paths with string concat instead of path.resolve; symlink-heavy setups where a relative shortcut seemed convenient.
Related errors
- Forbidden header: ${k}
- Plugin URL must use https
- Plugin URL must not contain userinfo
- Plugin URL must use a public host
- Subscription failed: Profile missing proxies or providers
AI-assisted analysis of mihomo-party-org/clash-party@911e090537 (2026-08-30).
Data as JSON: /api/errors/ba8678e3cb154503.
Report an issue: GitHub.