T09 · Insecure Skill Coding Practices
- Location
scripts/ssh.py:4- Finding
SSH Option Injection Through Unvalidated Host Argument
- Content
View full analysis
Vulnerability Details
File Location:
scripts/ssh.py:4-8
Vulnerability Type: SSH option injection leading to local command execution
Risk Level: Highpython parser = argparse.ArgumentParser() parser.add_argument('host') parser.add_argument('cmd', nargs='*') args = parser.parse_args() cmd = ['ssh', args.host] + (args.cmd or [])Technical Analysis
The positional
hostargument is passed directly to the OpenSSH client without validation or an effective option boundary. If this value begins with-, OpenSSH can interpret it as an option rather than as a destination hostname.Although
argparsenormally treats leading-dash values as options, an attacker can place its--end-of-options marker before the crafted positional argument. The resulting value is then copied unchanged into the SSH command. OpenSSH options such as-oProxyCommand=...can specify a local process that SSH executes while establishing a connection.Because
subprocess.run()receives an argument list rather than a shell command, conventional shell metacharacter injection is not the issue. The vulnerability instead arises from argument injection into the invoked SSH program and the dangerous semantics of accepted OpenSSH options.Attack Path
- An attacker gains control over, or influences, arguments supplied to the wrapper.
- The attacker uses the wrapper's
--separator to submit a leading-dash value as the positionalhost. - The crafted host contains an OpenSSH option such as
-oProxyCommand=.... - A subsequent positional value can act as the actual SSH destination.
- The wrapper constructs an argument vector equivalent to:
text ssh -oProxyCommand=<attacker-controlled command> <destination> - OpenSSH interprets the injected value as configuration and starts the attacker-selected proxy command locally.
This path is exploitable when an untrusted user, upstream agent, o ...[truncated 672 chars]
- Remediation
View remediation
Remediation Suggestions
-
Reject host values beginning with
-before invoking SSH:python if args.host.startswith('-'): parser.error('host must not begin with "-"') -
Strictly validate the destination against the hostname formats the tool intends to support, such as a DNS name, IP address, or controlled
user@hostform. Avoid accepting arbitrary SSH destination syntax unless explicitly required. -
Insert an end-of-options delimiter before the host if the supported OpenSSH implementation handles it reliably:
python cmd = ['ssh', '--', args.host] + args.cmdHost validation should still be retained as defense in depth and for portability.
-
If SSH options are required, define them as explicit wrapper arguments and allowlist only necessary options. Do not forward unrestricted OpenSSH configuration options from untrusted input.
-
Add regression tests covering leading-dash destinations, including
-oProxyCommand,-F,-S, and similar configuration-bearing options. -
Run the wrapper with the least privileges required and prevent untrusted callers from controlling its complete argument list.
-
