T09 · Insecure Skill Coding Practices
- Location
scripts/ssh_utils.py:105- Finding
SSH Connections Trust Unverified Host Keys
- Content
View full analysis
Vulnerability Details
File Location:
scripts/ssh_utils.py:105-121,scripts/ssh_utils.py:175-193,scripts/sms_agent_push.py:452-461,scripts/post_migration_verify.py:128-142,scripts/post_migration_verify.py:153-192, andscripts/migrate_worker.py:1378, 1391, 1403
Vulnerability Type: Missing SSH host identity verification
Risk Level: HighComplete Code Snippet
The central SSH wrapper uses
AutoAddPolicyfor both initial connections and reconnections:python client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) connect_kwargs = { "hostname": self.host, "port": self.port, "username": self.username, "timeout": timeout, } if self.key_path and os.path.exists(self.key_path): connect_kwargs["key_filename"] = self.key_path elif self.password: connect_kwargs["password"] = self.password client.connect(**connect_kwargs)python client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) connect_kwargs = { "hostname": _host, "port": _port, "username": _username, "timeout": timeout, } if _key_path and os.path.exists(_key_path): connect_kwargs["key_filename"] = _key_path elif _password: connect_kwargs["password"] = _password client.connect(**connect_kwargs)The post-migration proxy path applies the same policy to both the proxy and target:
python proxy_client = paramiko.SSHClient() proxy_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) proxy_kwargs = { "hostname": self.proxy_ip, "port": self.proxy_port, "username": self.proxy_username, "timeout": self.timeout, } if self.proxy_key_path and os.path.exists(self.proxy_key_path): proxy_kwargs["key_filename"] = self.proxy_key_path elif self.proxy_password: proxy_kwargs["password"] = self.proxy_password proxy_client.connect(**proxy ...[truncated 3179 chars]- Remediation
View remediation
Remediation Suggestions
- Replace
AutoAddPolicywith strict host-key validation:python client = paramiko.SSHClient() client.load_system_host_keys() client.load_host_keys(application_known_hosts) client.set_missing_host_key_policy(paramiko.RejectPolicy()) - Obtain expected ECS host-key fingerprints through an authenticated provisioning channel or require the user to approve a displayed fingerprint before the first connection.
- Maintain an application-specific
known_hostsfile with permissions restricted to the executing user. - Verify the hostname or IP, key algorithm, and fingerprint on every initial and re-established connection.
- Apply the same policy consistently to:
- Direct source and target connections
- Proxy ECS connections
- SSH connections established through proxy channels
- Reconnection logic
- Migration and post-migration verification paths
- Treat host-key changes as a hard failure unless the user explicitly authorizes a verified infrastructure replacement.
- Add automated tests that present an unknown or changed host key and confirm that the connection is rejected before credentials are submitted.
- Replace
