diff --git a/changelogs/fragments/dont_template_passwords_from_prompt.yml b/changelogs/fragments/dont_template_passwords_from_prompt.yml new file mode 100644 index 00000000000..86a0e6122f9 --- /dev/null +++ b/changelogs/fragments/dont_template_passwords_from_prompt.yml @@ -0,0 +1,2 @@ +bugfixes: + - resolves CVE-2019-10206, by avoiding templating passwords from prompt as it is probable they have special characters. diff --git a/lib/ansible/cli/__init__.py b/lib/ansible/cli/__init__.py index 9f87c7e88da..17807f271f4 100644 --- a/lib/ansible/cli/__init__.py +++ b/lib/ansible/cli/__init__.py @@ -29,6 +29,7 @@ from ansible.release import __version__ from ansible.utils.collection_loader import set_collection_playbook_paths from ansible.utils.display import Display from ansible.utils.path import unfrackpath +from ansible.utils.unsafe_proxy import AnsibleUnsafeBytes from ansible.vars.manager import VariableManager try: @@ -253,6 +254,13 @@ class CLI(with_metaclass(ABCMeta, object)): except EOFError: pass + # we 'wrap' the passwords to prevent templating as + # they can contain special chars and trigger it incorrectly + if sshpass: + sshpass = AnsibleUnsafeBytes(sshpass) + if becomepass: + becomepass = AnsibleUnsafeBytes(becomepass) + return (sshpass, becomepass) def validate_conflicts(self, op, runas_opts=False, fork_opts=False): diff --git a/lib/ansible/utils/unsafe_proxy.py b/lib/ansible/utils/unsafe_proxy.py index 2a180e6d4a4..35528f317bf 100644 --- a/lib/ansible/utils/unsafe_proxy.py +++ b/lib/ansible/utils/unsafe_proxy.py @@ -53,7 +53,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -from ansible.module_utils.six import string_types, text_type +from ansible.module_utils.six import string_types, text_type, binary_type from ansible.module_utils._text import to_text from ansible.module_utils.common._collections_compat import Mapping, MutableSequence, Set @@ -69,15 +69,18 @@ class AnsibleUnsafeText(text_type, AnsibleUnsafe): pass +class AnsibleUnsafeBytes(binary_type, AnsibleUnsafe): + pass + + class UnsafeProxy(object): def __new__(cls, obj, *args, **kwargs): # In our usage we should only receive unicode strings. # This conditional and conversion exists to sanity check the values # we're given but we may want to take it out for testing and sanitize # our input instead. - if isinstance(obj, string_types): - obj = to_text(obj, errors='surrogate_or_strict') - return AnsibleUnsafeText(obj) + if isinstance(obj, string_types) and not isinstance(obj, AnsibleUnsafeBytes): + obj = AnsibleUnsafeText(to_text(obj, errors='surrogate_or_strict')) return obj