copy - redact 'content' from invocation in check mode (#71033) (#71067)

* sanitize copy module invocation secrets in check mode

(cherry picked from commit 991714b9d1)
pull/71105/head
Sloane Hertel 4 years ago committed by GitHub
parent f41ff33ca6
commit 714cd2ad2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,7 @@
security_fixes:
- >
**security issue** - copy - Redact the value of the no_log 'content'
parameter in the result's invocation.module_args in check mode.
Previously when used with check mode and with '-vvv', the module
would not censor the content if a change would be made to the
destination path. (CVE-2020-14332)

@ -209,6 +209,8 @@ class ActionModule(ActionBase):
# NOTE: adding invocation arguments here needs to be kept in sync with # NOTE: adding invocation arguments here needs to be kept in sync with
# any no_log specified in the argument_spec in the module. # any no_log specified in the argument_spec in the module.
# This is not automatic. # This is not automatic.
# NOTE: do not add to this. This should be made a generic function for action plugins.
# This should also use the same argspec as the module instead of keeping it in sync.
if 'invocation' not in result: if 'invocation' not in result:
if self._play_context.no_log: if self._play_context.no_log:
result['invocation'] = "CENSORED: no_log is set" result['invocation'] = "CENSORED: no_log is set"
@ -218,8 +220,11 @@ class ActionModule(ActionBase):
result['invocation'] = self._task.args.copy() result['invocation'] = self._task.args.copy()
result['invocation']['module_args'] = self._task.args.copy() result['invocation']['module_args'] = self._task.args.copy()
if isinstance(result['invocation'], dict) and 'content' in result['invocation']: if isinstance(result['invocation'], dict):
result['invocation']['content'] = 'CENSORED: content is a no_log parameter' if 'content' in result['invocation']:
result['invocation']['content'] = 'CENSORED: content is a no_log parameter'
if result['invocation'].get('module_args', {}).get('content') is not None:
result['invocation']['module_args']['content'] = 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER'
return result return result

@ -74,6 +74,8 @@
- import_tasks: acls.yml - import_tasks: acls.yml
when: ansible_system == 'Linux' when: ansible_system == 'Linux'
- import_tasks: no_log.yml
- import_tasks: check_mode.yml - import_tasks: check_mode.yml
# https://github.com/ansible/ansible/issues/57618 # https://github.com/ansible/ansible/issues/57618

@ -0,0 +1,82 @@
- block:
- set_fact:
dest: "{{ local_temp_dir }}/test_no_log"
- name: ensure playbook and dest files don't exist yet
file:
path: "{{ item }}"
state: absent
loop:
- "{{ local_temp_dir }}/test_no_log.yml"
- "{{ dest }}"
- name: create a playbook to run with command
copy:
dest: "{{local_temp_dir}}/test_no_log.yml"
content: !unsafe |
---
- hosts: localhost
gather_facts: no
tasks:
- copy:
dest: "{{ dest }}"
content: "{{ secret }}"
- name: copy the secret while using -vvv and check mode
command: "ansible-playbook {{local_temp_dir}}/test_no_log.yml -vvv -e secret=SECRET -e dest={{dest}} --check"
register: result
- assert:
that:
- "'SECRET' not in result.stdout"
- name: copy the secret while using -vvv
command: "ansible-playbook {{local_temp_dir}}/test_no_log.yml -vvv -e secret=SECRET -e dest={{dest}}"
register: result
- assert:
that:
- "'SECRET' not in result.stdout"
- name: copy the secret while using -vvv and check mode again
command: "ansible-playbook {{local_temp_dir}}/test_no_log.yml -vvv -e secret=SECRET -e dest={{dest}} --check"
register: result
- assert:
that:
- "'SECRET' not in result.stdout"
- name: copy the secret while using -vvv again
command: "ansible-playbook {{local_temp_dir}}/test_no_log.yml -vvv -e secret=SECRET -e dest={{dest}}"
register: result
- assert:
that:
- "'SECRET' not in result.stdout"
- name: copy a new secret while using -vvv and check mode
command: "ansible-playbook {{local_temp_dir}}/test_no_log.yml -vvv -e secret=NEWSECRET -e dest={{dest}} --check"
register: result
- assert:
that:
- "'NEWSECRET' not in result.stdout"
- name: copy a new secret while using -vvv
command: "ansible-playbook {{local_temp_dir}}/test_no_log.yml -vvv -e secret=NEWSECRET -e dest={{dest}}"
register: result
- assert:
that:
- "'NEWSECRET' not in result.stdout"
always:
- name: remove temp test files
file:
path: "{{ item }}"
state: absent
loop:
- "{{ local_temp_dir }}/test_no_log.yml"
- "{{ dest }}"
Loading…
Cancel
Save