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

  1. Pass an absolute, normalized path (path.resolve) to grantTunPermissions so no '..' segment remains.
  2. Fix the user's custom core path setting to point directly at the binary (e.g. /opt/mihomo/mihomo).
  3. If building paths programmatically, use path.join/path.resolve rather than string concatenation.
  4. 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

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


AI-assisted analysis of mihomo-party-org/clash-party@911e090537 (2026-08-30). Data as JSON: /api/errors/ba8678e3cb154503. Report an issue: GitHub.