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
- Correct the username to a plain account name with no leading dash.
- Fix the parsing code that produced the malformed user value (verify the user@host split).
- 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
- Validate username shape (e.g. /^[a-z_][a-z0-9._-]*$/i) at entry time.
- When splitting 'user@host', check both halves before use.
- Never map free-form ssh arguments into the user field.
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
- Unsafe SSH target: host must not start with a dash ("${host}
- Unsafe SSH key path: must not start with a dash ("${keyPath}
- Unsafe SSH target: host contains control characters.
- Unsafe SSH target: user contains control characters.
- Unsafe SSH key path: contains control characters.
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/274e70867f10ba08.
Report an issue: GitHub.