VYPR
High severityNVD Advisory· Published Oct 23, 2018· Updated Aug 5, 2024

CVE-2018-16837

CVE-2018-16837

Description

Ansible "User" module leaks any data which is passed on as a parameter to ssh-keygen. This could lean in undesirable situations such as passphrases credentials passed as a parameter for the ssh-keygen executable. Showing those credentials in clear text form for every user which have access just to the process list.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Ansible User module leaks ssh-keygen passphrase credentials as clear-text arguments visible in the process list.

Vulnerability

The Ansible User module leaks any data passed as a parameter to ssh-keygen. When a passphrase credential is provided as a parameter for the ssh-keygen executable, the sensitive data appears in clear text on the command line. This affects Ansible versions prior to the fix introduced in pull request #47436, and is addressed in later releases (e.g., Ubuntu package updates as of USN-4072-1). [1][2][3][4]

Exploitation

An attacker with local system access and the ability to view the process list (for example, via ps or /proc) can observe the command-line arguments of ssh-keygen. No special privileges are needed beyond the ability to list processes on the same host where Ansible runs the User module task. [1][2]

Impact

The passphrase credential is exposed in plain text to any local user who can inspect running processes. This leads to disclosure of sensitive authentication material, potentially allowing the attacker to compromise SSH keys or other systems protected by the same passphrase. [1][2]

Mitigation

The vulnerability is fixed by not passing the ssh_key_passphrase on the command line; the fix is implemented in Ansible pull request #47436. Red Hat and Ubuntu have released updated packages (e.g., Ubuntu USN-4072-1). Users should upgrade to the patched version of Ansible containing the fix. If upgrading is not immediately possible, avoid using the ssh_key_passphrase parameter in the User module or ensure strict process list access controls. [3][4]

AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
ansiblePyPI
>= 2.7.0a1, < 2.7.12.7.1
ansiblePyPI
>= 2.6.0a1, < 2.6.72.6.7
ansiblePyPI
< 2.5.112.5.11

Affected products

150

Patches

3
f50cc0b8cb39

2.6: user: do not pass ssh_key_passphrase on cmdline (#47487)

https://github.com/ansible/ansibleMartin KrizekOct 31, 2018via ghsa
3 files changed · +82 4
  • changelogs/fragments/user-do-not-pass-ssh_key_passphrase-on-cmdline.yaml+2 0 added
    @@ -0,0 +1,2 @@
    +bugfixes:
    +  - user module - do not pass ssh_key_passphrase on cmdline (CVE-2018-16837)
    
  • lib/ansible/modules/system/user.py+52 4 modified
    @@ -354,13 +354,16 @@
     import grp
     import os
     import platform
    +import pty
     import pwd
    +import select
     import shutil
     import socket
    +import subprocess
     import time
     import re
     
    -from ansible.module_utils._text import to_native
    +from ansible.module_utils._text import to_native, to_bytes, to_text
     from ansible.module_utils.basic import load_platform_subclass, AnsibleModule
     
     try:
    @@ -821,13 +824,58 @@ def ssh_key_gen(self):
             cmd.append(self.ssh_comment)
             cmd.append('-f')
             cmd.append(ssh_key_file)
    -        cmd.append('-N')
             if self.ssh_passphrase is not None:
    -            cmd.append(self.ssh_passphrase)
    +            if self.module.check_mode:
    +                self.module.debug('In check mode, would have run: "%s"' % cmd)
    +                return (0, '', '')
    +
    +            master_in_fd, slave_in_fd = pty.openpty()
    +            master_out_fd, slave_out_fd = pty.openpty()
    +            master_err_fd, slave_err_fd = pty.openpty()
    +            env = os.environ.copy()
    +            env['LC_ALL'] = 'C'
    +            try:
    +                p = subprocess.Popen([to_bytes(c) for c in cmd],
    +                                     stdin=slave_in_fd,
    +                                     stdout=slave_out_fd,
    +                                     stderr=slave_err_fd,
    +                                     preexec_fn=os.setsid,
    +                                     env=env)
    +                out_buffer = b''
    +                err_buffer = b''
    +                while p.poll() is None:
    +                    r, w, e = select.select([master_out_fd, master_err_fd], [], [], 1)
    +                    first_prompt = b'Enter passphrase (empty for no passphrase):'
    +                    second_prompt = b'Enter same passphrase again'
    +                    prompt = first_prompt
    +                    for fd in r:
    +                        if fd == master_out_fd:
    +                            chunk = os.read(master_out_fd, 10240)
    +                            out_buffer += chunk
    +                            if prompt in out_buffer:
    +                                os.write(master_in_fd, to_bytes(self.ssh_passphrase, errors='strict') + b'\r')
    +                                prompt = second_prompt
    +                        else:
    +                            chunk = os.read(master_err_fd, 10240)
    +                            err_buffer += chunk
    +                            if prompt in err_buffer:
    +                                os.write(master_in_fd, to_bytes(self.ssh_passphrase, errors='strict') + b'\r')
    +                                prompt = second_prompt
    +                        if b'Overwrite (y/n)?' in out_buffer or b'Overwrite (y/n)?' in err_buffer:
    +                            # The key was created between us checking for existence and now
    +                            return (None, 'Key already exists', '')
    +
    +                rc = p.returncode
    +                out = to_native(out_buffer)
    +                err = to_native(err_buffer)
    +            except OSError as e:
    +                return (1, '', to_native(e))
             else:
    +            cmd.append('-N')
                 cmd.append('')
     
    -        (rc, out, err) = self.execute_command(cmd)
    +            (rc, out, err) = self.execute_command(cmd)
    +
             if rc == 0 and not self.module.check_mode:
                 # If the keys were successfully created, we should be able
                 # to tweak ownership.
    
  • test/integration/targets/user/tasks/main.yml+28 0 modified
    @@ -430,3 +430,31 @@
             that:
               - bsd_account_expiration.stdout == '0'
       when: ansible_os_family == 'FreeBSD'
    +
    +# Test creating ssh key with passphrase
    +- name: Remove ansibulluser
    +  user:
    +    name: ansibulluser
    +    state: absent
    +
    +- name: Create user with ssh key
    +  user:
    +    name: ansibulluser
    +    state: present
    +    generate_ssh_key: yes
    +    ssh_key_file: "{{ output_dir }}/test_id_rsa"
    +    ssh_key_passphrase: secret_passphrase
    +
    +- name: Unlock ssh key
    +  command: "ssh-keygen -y -f {{ output_dir }}/test_id_rsa -P secret_passphrase"
    +  register: result
    +
    +- name: Check that ssh key was unlocked successfully
    +  assert:
    +    that:
    +      - result.rc == 0
    +
    +- name: Clean ssh key
    +  file:
    +    path: "{{ output_dir }}/test_id_rsa"
    +    state: absent
    
77928e6c3a2a

2.5: user: do not pass ssh_key_passphrase on cmdline (#47486)

https://github.com/ansible/ansibleMartin KrizekOct 24, 2018via ghsa
3 files changed · +82 4
  • changelogs/fragments/user-do-not-pass-ssh_key_passphrase-on-cmdline.yaml+2 0 added
    @@ -0,0 +1,2 @@
    +bugfixes:
    +  - user module - do not pass ssh_key_passphrase on cmdline (CVE-2018-16837)
    
  • lib/ansible/modules/system/user.py+52 4 modified
    @@ -325,13 +325,16 @@
     import grp
     import os
     import platform
    +import pty
     import pwd
    +import select
     import shutil
     import socket
    +import subprocess
     import time
     import re
     
    -from ansible.module_utils._text import to_native
    +from ansible.module_utils._text import to_native, to_bytes, to_text
     from ansible.module_utils.basic import load_platform_subclass, AnsibleModule
     
     try:
    @@ -774,13 +777,58 @@ def ssh_key_gen(self):
             cmd.append(self.ssh_comment)
             cmd.append('-f')
             cmd.append(ssh_key_file)
    -        cmd.append('-N')
             if self.ssh_passphrase is not None:
    -            cmd.append(self.ssh_passphrase)
    +            if self.module.check_mode:
    +                self.module.debug('In check mode, would have run: "%s"' % cmd)
    +                return (0, '', '')
    +
    +            master_in_fd, slave_in_fd = pty.openpty()
    +            master_out_fd, slave_out_fd = pty.openpty()
    +            master_err_fd, slave_err_fd = pty.openpty()
    +            env = os.environ.copy()
    +            env['LC_ALL'] = 'C'
    +            try:
    +                p = subprocess.Popen([to_bytes(c) for c in cmd],
    +                                     stdin=slave_in_fd,
    +                                     stdout=slave_out_fd,
    +                                     stderr=slave_err_fd,
    +                                     preexec_fn=os.setsid,
    +                                     env=env)
    +                out_buffer = b''
    +                err_buffer = b''
    +                while p.poll() is None:
    +                    r, w, e = select.select([master_out_fd, master_err_fd], [], [], 1)
    +                    first_prompt = b'Enter passphrase (empty for no passphrase):'
    +                    second_prompt = b'Enter same passphrase again'
    +                    prompt = first_prompt
    +                    for fd in r:
    +                        if fd == master_out_fd:
    +                            chunk = os.read(master_out_fd, 10240)
    +                            out_buffer += chunk
    +                            if prompt in out_buffer:
    +                                os.write(master_in_fd, to_bytes(self.ssh_passphrase, errors='strict') + b'\r')
    +                                prompt = second_prompt
    +                        else:
    +                            chunk = os.read(master_err_fd, 10240)
    +                            err_buffer += chunk
    +                            if prompt in err_buffer:
    +                                os.write(master_in_fd, to_bytes(self.ssh_passphrase, errors='strict') + b'\r')
    +                                prompt = second_prompt
    +                        if b'Overwrite (y/n)?' in out_buffer or b'Overwrite (y/n)?' in err_buffer:
    +                            # The key was created between us checking for existence and now
    +                            return (None, 'Key already exists', '')
    +
    +                rc = p.returncode
    +                out = to_native(out_buffer)
    +                err = to_native(err_buffer)
    +            except OSError as e:
    +                return (1, '', to_native(e))
             else:
    +            cmd.append('-N')
                 cmd.append('')
     
    -        (rc, out, err) = self.execute_command(cmd)
    +            (rc, out, err) = self.execute_command(cmd)
    +
             if rc == 0 and not self.module.check_mode:
                 # If the keys were successfully created, we should be able
                 # to tweak ownership.
    
  • test/integration/targets/user/tasks/main.yml+28 0 modified
    @@ -246,3 +246,31 @@
         - name: Restore original timezone - {{ original_timezone.diff.before.name }}
           timezone:
             name: "{{ original_timezone.diff.before.name }}"
    +
    +# Test creating ssh key with passphrase
    +- name: Remove ansibulluser
    +  user:
    +    name: ansibulluser
    +    state: absent
    +
    +- name: Create user with ssh key
    +  user:
    +    name: ansibulluser
    +    state: present
    +    generate_ssh_key: yes
    +    ssh_key_file: "{{ output_dir }}/test_id_rsa"
    +    ssh_key_passphrase: secret_passphrase
    +
    +- name: Unlock ssh key
    +  command: "ssh-keygen -y -f {{ output_dir }}/test_id_rsa -P secret_passphrase"
    +  register: result
    +
    +- name: Check that ssh key was unlocked successfully
    +  assert:
    +    that:
    +      - result.rc == 0
    +
    +- name: Clean ssh key
    +  file:
    +    path: "{{ output_dir }}/test_id_rsa"
    +    state: absent
    
b618339c321c

2.7: user: do not pass ssh_key_passphrase on cmdline (#47445)

https://github.com/ansible/ansibleMartin KrizekOct 23, 2018via ghsa
4 files changed · +84 5
  • changelogs/fragments/user-do-not-pass-ssh_key_passphrase-on-cmdline.yaml+2 0 added
    @@ -0,0 +1,2 @@
    +bugfixes:
    +  - user module - do not pass ssh_key_passphrase on cmdline (CVE-2018-16837)
    
  • lib/ansible/modules/system/user.py+52 5 modified
    @@ -355,13 +355,15 @@
     import os
     import re
     import platform
    +import pty
     import pwd
    +import select
     import shutil
     import socket
    +import subprocess
     import time
    -import re
     
    -from ansible.module_utils._text import to_native
    +from ansible.module_utils._text import to_native, to_bytes, to_text
     from ansible.module_utils.basic import load_platform_subclass, AnsibleModule
     
     try:
    @@ -860,13 +862,58 @@ def ssh_key_gen(self):
             cmd.append(self.ssh_comment)
             cmd.append('-f')
             cmd.append(ssh_key_file)
    -        cmd.append('-N')
             if self.ssh_passphrase is not None:
    -            cmd.append(self.ssh_passphrase)
    +            if self.module.check_mode:
    +                self.module.debug('In check mode, would have run: "%s"' % cmd)
    +                return (0, '', '')
    +
    +            master_in_fd, slave_in_fd = pty.openpty()
    +            master_out_fd, slave_out_fd = pty.openpty()
    +            master_err_fd, slave_err_fd = pty.openpty()
    +            env = os.environ.copy()
    +            env['LC_ALL'] = 'C'
    +            try:
    +                p = subprocess.Popen([to_bytes(c) for c in cmd],
    +                                     stdin=slave_in_fd,
    +                                     stdout=slave_out_fd,
    +                                     stderr=slave_err_fd,
    +                                     preexec_fn=os.setsid,
    +                                     env=env)
    +                out_buffer = b''
    +                err_buffer = b''
    +                while p.poll() is None:
    +                    r, w, e = select.select([master_out_fd, master_err_fd], [], [], 1)
    +                    first_prompt = b'Enter passphrase (empty for no passphrase):'
    +                    second_prompt = b'Enter same passphrase again'
    +                    prompt = first_prompt
    +                    for fd in r:
    +                        if fd == master_out_fd:
    +                            chunk = os.read(master_out_fd, 10240)
    +                            out_buffer += chunk
    +                            if prompt in out_buffer:
    +                                os.write(master_in_fd, to_bytes(self.ssh_passphrase, errors='strict') + b'\r')
    +                                prompt = second_prompt
    +                        else:
    +                            chunk = os.read(master_err_fd, 10240)
    +                            err_buffer += chunk
    +                            if prompt in err_buffer:
    +                                os.write(master_in_fd, to_bytes(self.ssh_passphrase, errors='strict') + b'\r')
    +                                prompt = second_prompt
    +                        if b'Overwrite (y/n)?' in out_buffer or b'Overwrite (y/n)?' in err_buffer:
    +                            # The key was created between us checking for existence and now
    +                            return (None, 'Key already exists', '')
    +
    +                rc = p.returncode
    +                out = to_native(out_buffer)
    +                err = to_native(err_buffer)
    +            except OSError as e:
    +                return (1, '', to_native(e))
             else:
    +            cmd.append('-N')
                 cmd.append('')
     
    -        (rc, out, err) = self.execute_command(cmd)
    +            (rc, out, err) = self.execute_command(cmd)
    +
             if rc == 0 and not self.module.check_mode:
                 # If the keys were successfully created, we should be able
                 # to tweak ownership.
    
  • test/integration/targets/user/tasks/main.yml+29 0 modified
    @@ -493,3 +493,32 @@
               - result.bakup
               - shadow_backups.files | map(attribute='path') | list | length > 0
       when: ansible_os_family == 'Solaris'
    +
    +
    +# Test creating ssh key with passphrase
    +- name: Remove ansibulluser
    +  user:
    +    name: ansibulluser
    +    state: absent
    +
    +- name: Create user with ssh key
    +  user:
    +    name: ansibulluser
    +    state: present
    +    generate_ssh_key: yes
    +    ssh_key_file: "{{ output_dir }}/test_id_rsa"
    +    ssh_key_passphrase: secret_passphrase
    +
    +- name: Unlock ssh key
    +  command: "ssh-keygen -y -f {{ output_dir }}/test_id_rsa -P secret_passphrase"
    +  register: result
    +
    +- name: Check that ssh key was unlocked successfully
    +  assert:
    +    that:
    +      - result.rc == 0
    +
    +- name: Clean ssh key
    +  file:
    +    path: "{{ output_dir }}/test_id_rsa"
    +    state: absent
    
  • test/sanity/validate-modules/ignore.txt+1 0 modified
    @@ -1141,6 +1141,7 @@ lib/ansible/modules/system/svc.py E322
     lib/ansible/modules/system/svc.py E324
     lib/ansible/modules/system/ufw.py E322
     lib/ansible/modules/system/ufw.py E326
    +lib/ansible/modules/system/user.py E210
     lib/ansible/modules/system/user.py E324
     lib/ansible/modules/system/user.py E327
     lib/ansible/modules/system/vdo.py E324
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

27

News mentions

0

No linked articles in our index yet.