summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Martz <matt@sivel.net>2021-09-29 11:53:40 -0500
committerGitHub <noreply@github.com>2021-09-29 11:53:40 -0500
commit2cdc3834c94328b62d820542e68251e22014e0a8 (patch)
tree3a5074c77091b5b16ff2263445696df1fdd56baa
parenta00c61719b825c21c629d25244715c82716548e3 (diff)
downloadansible-2cdc3834c94328b62d820542e68251e22014e0a8.tar.gz
[stable-2.10] Don't show params when there is an issue with `set_option(s)` (#75805) (#75809)
(cherry picked from commit 79e9dae) Co-authored-by: Matt Martz <matt@sivel.net>
-rw-r--r--changelogs/fragments/avoid-set_options-leak.yaml5
-rwxr-xr-xlib/ansible/cli/scripts/ansible_connection_cli_stub.py12
-rw-r--r--lib/ansible/module_utils/connection.py5
-rw-r--r--test/units/module_utils/test_connection.py22
4 files changed, 42 insertions, 2 deletions
diff --git a/changelogs/fragments/avoid-set_options-leak.yaml b/changelogs/fragments/avoid-set_options-leak.yaml
new file mode 100644
index 0000000000..9680f444e6
--- /dev/null
+++ b/changelogs/fragments/avoid-set_options-leak.yaml
@@ -0,0 +1,5 @@
+---
+security_fixes:
+ - Do not include params in exception when a call to ``set_options`` fails.
+ Additionally, block the exception that is returned from being displayed to stdout.
+ (CVE-2021-3620)
diff --git a/lib/ansible/cli/scripts/ansible_connection_cli_stub.py b/lib/ansible/cli/scripts/ansible_connection_cli_stub.py
index d701f15696..08c36d6ec4 100755
--- a/lib/ansible/cli/scripts/ansible_connection_cli_stub.py
+++ b/lib/ansible/cli/scripts/ansible_connection_cli_stub.py
@@ -100,7 +100,11 @@ class ConnectionProcess(object):
self.play_context.private_key_file = os.path.join(self.original_path, self.play_context.private_key_file)
self.connection = connection_loader.get(self.play_context.connection, self.play_context, '/dev/null',
task_uuid=self._task_uuid, ansible_playbook_pid=self._ansible_playbook_pid)
- self.connection.set_options(var_options=variables)
+ try:
+ self.connection.set_options(var_options=variables)
+ except ConnectionError as exc:
+ messages.append(('debug', to_text(exc)))
+ raise ConnectionError('Unable to decode JSON from response set_options. See the debug log for more information.')
self.connection._socket_path = self.socket_path
self.srv.register(self.connection)
@@ -302,7 +306,11 @@ def main():
else:
messages.append(('vvvv', 'found existing local domain socket, using it!'))
conn = Connection(socket_path)
- conn.set_options(var_options=variables)
+ try:
+ conn.set_options(var_options=variables)
+ except ConnectionError as exc:
+ messages.append(('debug', to_text(exc)))
+ raise ConnectionError('Unable to decode JSON from response set_options. See the debug log for more information.')
pc_data = to_text(init_data)
try:
conn.update_play_context(pc_data)
diff --git a/lib/ansible/module_utils/connection.py b/lib/ansible/module_utils/connection.py
index a76fdb6bcc..fd0b134087 100644
--- a/lib/ansible/module_utils/connection.py
+++ b/lib/ansible/module_utils/connection.py
@@ -163,6 +163,11 @@ class Connection(object):
try:
response = json.loads(out)
except ValueError:
+ # set_option(s) has sensitive info, and the details are unlikely to matter anyway
+ if name.startswith("set_option"):
+ raise ConnectionError(
+ "Unable to decode JSON from response to {0}. Received '{1}'.".format(name, out)
+ )
params = [repr(arg) for arg in args] + ['{0}={1!r}'.format(k, v) for k, v in iteritems(kwargs)]
params = ', '.join(params)
raise ConnectionError(
diff --git a/test/units/module_utils/test_connection.py b/test/units/module_utils/test_connection.py
new file mode 100644
index 0000000000..bd0285b3a7
--- /dev/null
+++ b/test/units/module_utils/test_connection.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright: (c) 2021, Matt Martz <matt@sivel.net>
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+from ansible.module_utils import connection
+
+import pytest
+
+
+def test_set_options_credential_exposure():
+ def send(data):
+ return '{'
+
+ c = connection.Connection(connection.__file__)
+ c.send = send
+ with pytest.raises(connection.ConnectionError) as excinfo:
+ c._exec_jsonrpc('set_options', become_pass='password')
+
+ assert 'password' not in str(excinfo.value)