Skip to content

Commit

Permalink
copy - redact 'content' from invocation in check mode (#71033) (#71069)
Browse files Browse the repository at this point in the history
* sanitize copy module invocation secrets in check mode

(cherry picked from commit 991714b)
  • Loading branch information
s-hertel committed Aug 7, 2020
1 parent 11738ae commit 291f949
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 2 deletions.
@@ -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)
9 changes: 7 additions & 2 deletions lib/ansible/plugins/action/copy.py
Expand Up @@ -212,6 +212,8 @@ def _ensure_invocation(self, result):
# NOTE: adding invocation arguments here needs to be kept in sync with
# any no_log specified in the argument_spec in the module.
# 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 self._play_context.no_log:
result['invocation'] = "CENSORED: no_log is set"
Expand All @@ -221,8 +223,11 @@ def _ensure_invocation(self, result):
result['invocation'] = self._task.args.copy()
result['invocation']['module_args'] = self._task.args.copy()

if isinstance(result['invocation'], dict) and 'content' in result['invocation']:
result['invocation']['content'] = 'CENSORED: content is a no_log parameter'
if isinstance(result['invocation'], dict):
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

Expand Down
2 changes: 2 additions & 0 deletions test/integration/targets/copy/tasks/main.yml
Expand Up @@ -61,6 +61,8 @@
- import_tasks: acls.yml
when: ansible_system == 'Linux'

- import_tasks: no_log.yml

# https://github.com/ansible/ansible/issues/57618
- name: Test diff contents
copy:
Expand Down
82 changes: 82 additions & 0 deletions test/integration/targets/copy/tasks/no_log.yml
@@ -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 }}"

0 comments on commit 291f949

Please sign in to comment.