{"id":"CVE-2026-126641","kind":"vulnerability","aliases":["CVE-2026-126641"],"related":[],"title":"Ansible libssh plugin accepts changed SSH host keys, enabling machine-in-the-middle","description":"A host key verification flaw was found in ansible-pylibssh and in the ansible.netcommon libssh connection plugin. When trust-on-first-use is enabled (host_key_auto_add on the libssh connection plugin, or AutoAddPolicy in ansible-pylibssh), a host that is already present in known_hosts but now presents a different key is accepted without warning. The pylibssh Session.verify_knownhost() method passes the SSH_KNOWN_HOSTS_CHANGED and SSH_KNOWN_HOSTS_OTHER states to the same missing_host_key() policy hook used for unknown hosts, and the bundled AutoAddPolicy/RejectPolicy classes (as well as ansible.netcommon's MyAddPolicy, which is modeled on paramiko's AutoAddPolicy) therefore add the changed key and continue the connection rather than aborting as paramiko's BadHostKeyException path would. As a result the controller authenticates to the substitute host, runs the play there, and appends the new key to known_hosts, which can disclose connection credentials to an attacker performing a machine-in-the-middle attack. Default configurations (host_key_checking enabled, host_key_auto_add unset) are not affected; non-interactive runs fail closed.","summary":"When trust-on-first-use is enabled, the Ansible libssh connection plugin and ansible-pylibssh accept a host whose SSH key has changed from the one in known_hosts, and append the new key. An attacker positioned on the network path can impersonate the managed host and receive the connection credentials.","severity":"medium","cvss":6.5,"epss":null,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["ansible","ansible-pylibssh","ansible.netcommon","libssh","package"],"not_affected_if":["default-config","host_key_checking-enabled","non-interactive-run"],"how_to_check":"- Check whether `host_key_auto_add` is enabled for the libssh connection plugin in the Ansible configuration or inventory.\n- Check whether ansible-pylibssh's `AutoAddPolicy` is used in any script or plugin in the controller.\n- Confirm `host_key_checking` is still enabled in `ansible.cfg`.","fix":null,"status":"open","published_at":"2026-11-12T11:17:11+00:00","first_seen_at":"2026-11-12T11:38:04+00:00","triaged_at":"2026-11-12T11:40:06+00:00","updated_at":"2026-11-12T11:40:06+00:00","category":"package","confidence":0.7,"triage":{"at":"2026-11-12T11:40:06Z","model":"claude-haiku-5-5","output":{"fix":"unknown","reach":"network","title":"Ansible libssh plugin accepts changed SSH host keys, enabling machine-in-the-middle","impact":"medium","summary":"When trust-on-first-use is enabled, the Ansible libssh connection plugin and ansible-pylibssh accept a host whose SSH key has changed from the one in known_hosts, and append the new key. An attacker positioned on the network path can impersonate the managed host and receive the connection credentials.","audience":"developers","category":"package","nicknames":[],"who_cares":["ansible","ansible-pylibssh","ansible.netcommon","libssh"],"confidence":0.7,"fix_status":"unknown","needs_auth":"no","worst_case":"Connection credentials sent to an impersonating host via machine-in-the-middle","analyst_note":"Find the fixed versions of ansible-pylibssh and ansible.netcommon from the NVD entry or the upstream advisory; the sources given do not name them.","how_to_check":"- Check whether `host_key_auto_add` is enabled for the libssh connection plugin in the Ansible configuration or inventory.\n- Check whether ansible-pylibssh's `AutoAddPolicy` is used in any script or plugin in the controller.\n- Confirm `host_key_checking` is still enabled in `ansible.cfg`.","plain_action":"","product_name":"","needs_analyst":true,"not_affected_if":["default-config","host_key_checking-enabled","non-interactive-run"],"who_is_affected":"Only controllers that use the libssh connection plugin or ansible-pylibssh with trust-on-first-use turned on (host_key_auto_add set, or AutoAddPolicy in use). Default configurations, where host_key_checking is enabled and host_key_auto_add is unset, are not affected, and non-interactive runs fail closed. The sources do not name the fixed versions.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"medium"},"cost_usd":0.000835,"input_tokens":4877,"output_tokens":695,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-126641':17A,20A '-2026':16A,19A 'abort':199C 'accept':4A,45B,138C 'add':110C,189C,253C 'affect':257C 'alreadi':126C 'ansibl':1A,21B,23B,37B,43B,90C,120C 'ansible-pylibssh':22B,42B,89C,119C 'ansible.netcommon':25B,95C,178C 'append':60B,221C 'attack':65B,235C,243C 'authent':211C 'auto':109C,252C 'autoaddpolici':117C,187C 'autoaddpolicy/rejectpolicy':173C 'badhostkeyexcept':203C 'bundl':172C 'chang':5A,52B,151C,191C 'check':248C 'class':174C 'close':263C 'configur':245C 'connect':39B,79B,97C,114C,196C,231C 'continu':194C 'control':210C 'credenti':80B,232C 'cve':15A,18A 'default':244C 'differ':135C 'disclos':230C 'enabl':9A,35B,106C,249C 'fail':262C 'first':32B,103C 'flaw':85C 'found':87C 'hook':165C 'host':7A,47B,58B,75B,82C,107C,123C,130C,150C,155C,162C,169C,215C,227C,246C,250C 'imperson':72B 'interact':260C 'key':8A,50B,63B,83C,108C,136C,163C,192C,224C,247C,251C 'known':57B,129C,149C,154C,226C 'knownhost':144C 'libssh':2A,26B,38B,96C,113C 'machin':11A,239C 'machine-in-the-middl':10A,238C 'manag':74B 'method':145C 'middl':14A,242C 'miss':161C 'model':183C 'myaddpolici':180C 'network':69B 'new':62B,223C 'non':259C 'non-interact':258C 'one':55B 'packag':27B 'paramiko':185C,201C 'pass':146C 'path':70B,204C 'perform':236C 'play':218C 'plugin':3A,40B,98C,115C 'polici':164C 'posit':66B 'present':127C,133C 'pylibssh':24B,44B,91C,121C,142C 'rather':197C 'receiv':77B 'result':208C 'run':216C,261C 'session.verify':143C 'ssh':6A,49B,148C,153C 'state':157C 'substitut':214C 'therefor':188C 'trust':30B,101C 'trust-on-first-us':29B,100C 'unknown':168C 'unset':254C 'use':33B,104C,166C 'verif':84C 'warn':140C 'well':176C 'whose':48B 'without':139C 'would':205C","nicknames":[],"mitigations":[],"who_affected":"Only controllers that use the libssh connection plugin or ansible-pylibssh with trust-on-first-use turned on (host_key_auto_add set, or AutoAddPolicy in use). Default configurations, where host_key_checking is enabled and host_key_auto_add is unset, are not affected, and non-interactive runs fail closed. The sources do not name the fixed versions.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"none","audience":"developers","plain_action":null,"pkeys":[],"ptokens":[],"labels":["ansible","ansiblenetcommon","ansiblepylibssh","libssh","medium","package"],"campaign_type":null,"search_a":"'-126641':17A,20A '-2026':16A,19A 'accept':4A 'ansibl':1A 'chang':5A 'cve':15A,18A 'enabl':9A 'host':7A 'key':8A 'libssh':2A 'machin':11A 'machine-in-the-middl':10A 'middl':14A 'plugin':3A 'ssh':6A","search_b":"'accept':45B 'ansibl':21B,23B,37B,43B 'ansible-pylibssh':22B,42B 'ansible.netcommon':25B 'append':60B 'attack':65B 'chang':52B 'connect':39B,79B 'credenti':80B 'enabl':35B 'first':32B 'host':47B,58B,75B 'imperson':72B 'key':50B,63B 'known':57B 'libssh':26B,38B 'manag':74B 'network':69B 'new':62B 'one':55B 'packag':27B 'path':70B 'plugin':40B 'posit':66B 'pylibssh':24B,44B 'receiv':77B 'ssh':49B 'trust':30B 'trust-on-first-us':29B 'use':33B 'whose':48B","search_c":"'abort':199C 'accept':138C 'add':110C,189C,253C 'affect':257C 'alreadi':126C 'ansibl':90C,120C 'ansible-pylibssh':89C,119C 'ansible.netcommon':95C,178C 'append':221C 'attack':235C,243C 'authent':211C 'auto':109C,252C 'autoaddpolici':117C,187C 'autoaddpolicy/rejectpolicy':173C 'badhostkeyexcept':203C 'bundl':172C 'chang':151C,191C 'check':248C 'class':174C 'close':263C 'configur':245C 'connect':97C,114C,196C,231C 'continu':194C 'control':210C 'credenti':232C 'default':244C 'differ':135C 'disclos':230C 'enabl':106C,249C 'fail':262C 'first':103C 'flaw':85C 'found':87C 'hook':165C 'host':82C,107C,123C,130C,150C,155C,162C,169C,215C,227C,246C,250C 'interact':260C 'key':83C,108C,136C,163C,192C,224C,247C,251C 'known':129C,149C,154C,226C 'knownhost':144C 'libssh':96C,113C 'machin':239C 'machine-in-the-middl':238C 'method':145C 'middl':242C 'miss':161C 'model':183C 'myaddpolici':180C 'new':223C 'non':259C 'non-interact':258C 'paramiko':185C,201C 'pass':146C 'path':204C 'perform':236C 'play':218C 'plugin':98C,115C 'polici':164C 'present':127C,133C 'pylibssh':91C,121C,142C 'rather':197C 'result':208C 'run':216C,261C 'session.verify':143C 'ssh':148C,153C 'state':157C 'substitut':214C 'therefor':188C 'trust':101C 'trust-on-first-us':100C 'unknown':168C 'unset':254C 'use':104C,166C 'verif':84C 'warn':140C 'well':176C 'without':139C 'would':205C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-11-12T11:17:11+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N","cvss_by":"secalert@redhat.com","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-126641","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-126641","severity":null,"published_at":"2026-11-12T11:17:11+00:00","modified_at":"2026-11-12T11:17:11+00:00","first_seen_at":"2026-11-12T11:38:04+00:00","fetched_at":"2026-11-12T11:38:04+00:00","note":null}],"documents":[],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}