Repository: ansible/ansible

Issue:
Become password containing invalid Jinja2 syntax causes template error
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and devel branch are affected too.
-->

##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
become

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.4.3.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'<homedir redacted>/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.6 (default, Nov 23 2017, 15:49:48) [GCC 4.8.4]
```

##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
(None)

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->
Ubuntu 14.04.5 LTS (both hosts)

##### SUMMARY
<!--- Explain the problem briefly -->
When using `--ask-become-pass` with either `ansible` or `ansible-playbook`, and the password contains invalid Jinja2 syntax, the execution of the first task with `become: yes` fails with a jinja2 related error.


##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```
ansible -K examplehost -a 'echo test'
SUDO password: test{{
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
```
examplehost | SUCCESS | rc=0 >>
test
```

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
examplehost | FAILED | rc=-1 >>
template error while templating string: unexpected 'end of template'. String: test{{
```
(No extra information with `-vvv`)


Discussion:
Files identified in the description:
* [lib/ansible/playbook/become.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/playbook/become.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
Still happens in 2.5.1

Resolving patch:
diff --git a/lib/ansible/cli/__init__.py b/lib/ansible/cli/__init__.py
--- a/lib/ansible/cli/__init__.py
+++ b/lib/ansible/cli/__init__.py
@@ -38,6 +38,7 @@
 from ansible.inventory.manager import InventoryManager
 from ansible.module_utils.six import with_metaclass, string_types
 from ansible.module_utils._text import to_bytes, to_text
+from ansible.utils.unsafe_proxy import AnsibleUnsafeText
 from ansible.parsing.dataloader import DataLoader
 from ansible.release import __version__
 from ansible.utils.path import unfrackpath
@@ -329,7 +330,7 @@ def ask_passwords(self):
                 sshpass = getpass.getpass(prompt="SSH password: ")
                 become_prompt = "%s password[defaults to SSH password]: " % become_prompt_method
                 if sshpass:
-                    sshpass = to_bytes(sshpass, errors='strict', nonstring='simplerepr')
+                    sshpass = AnsibleUnsafeText(to_bytes(sshpass, errors='strict', nonstring='simplerepr'))
             else:
                 become_prompt = "%s password: " % become_prompt_method
 
@@ -338,7 +339,7 @@ def ask_passwords(self):
                 if op.ask_pass and becomepass == '':
                     becomepass = sshpass
                 if becomepass:
-                    becomepass = to_bytes(becomepass)
+                    becomepass = AnsibleUnsafeText(to_bytes(becomepass))
         except EOFError:
             pass
 


Test patch: