NousResearch/hermes-agent · error · Error

Unsafe SSH target: user must not start with a dash ("${user}

Error message

Unsafe SSH target: user must not start with a dash ("${user}").

What it means

Thrown by validateSshTarget() when the user field starts with a dash. Like the host check, this prevents the value being consumed as an ssh option flag once interpolated into the command line (e.g. via user@host argument construction).

Source

Thrown at apps/desktop/electron/ssh-connection.ts:65

function validateSshTarget(host, user, port) {
  if (!host || typeof host !== 'string') {
    throw new Error('Unsafe SSH target: host is required.')
  }

  if (host.startsWith('-')) {
    throw new Error(`Unsafe SSH target: host must not start with a dash ("${host}").`)
  }

  if (_CONTROL_CHAR_RE.test(host)) {
    throw new Error('Unsafe SSH target: host contains control characters.')
  }

  if (user && _CONTROL_CHAR_RE.test(user)) {
    throw new Error('Unsafe SSH target: user contains control characters.')
  }

  if (user && user.startsWith('-')) {
    throw new Error(`Unsafe SSH target: user must not start with a dash ("${user}").`)
  }

  const p = Number(port)

  if (!Number.isInteger(p) || p < 1 || p > 65535) {
    throw new Error(`Unsafe SSH port: ${port} (must be 1-65535).`)
  }
}

function validateKeyPath(keyPath) {
  if (!keyPath) {
    return
  }

  if (_CONTROL_CHAR_RE.test(keyPath)) {
    throw new Error('Unsafe SSH key path: contains control characters.')
  }

View on GitHub (pinned to c896c09c42)

Solutions

  1. Correct the username to a plain account name with no leading dash.
  2. Fix the parsing code that produced the malformed user value (verify the user@host split).
  3. Validate username shape at the config/UI layer with a leading-dash rejection like the host field.

Example fix

// before
const [user, host] = rawTarget.split('@') // rawTarget = '-oX@host'

// after
const [user, host] = rawTarget.split('@')
if (user.startsWith('-')) throw new TypeError(`invalid username: ${user}`)
Defensive patterns

Strategy: validation

Validate before calling

if (user && typeof user === 'string' && user.startsWith('-')) {
  rejectConfig('SSH user must not start with a dash')
}

Type guard

function isDashSafeUser(u: unknown): u is string {
  return typeof u === 'string' && !u.startsWith('-')
}

Try / catch

try {
  validateSshTarget(host, user, port)
} catch (e) {
  if (e instanceof Error && e.message.includes('user must not start with a dash')) {
    // not sanitizable: the value is option-shaped; reject the config
    invalidateRemoteConfig('username field contains an ssh-flag-like value')
    return
  }
  throw e
}

Prevention

When it happens

Trigger: cfg.user values such as '-o...' or any truthy string beginning with '-'. Arises from a mis-parsed combined target string or malicious config input.

Common situations: Splitting 'user@host' where the split produced a leading-dash fragment; user pasting an ssh flag into the username field; crafted config attempting option injection through the user slot.

Related errors


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/274e70867f10ba08. Report an issue: GitHub.