VYPR
Moderate severityNVD Advisory· Published Sep 11, 2020· Updated Aug 4, 2024

CVE-2020-14332

CVE-2020-14332

Description

A flaw was found in the Ansible Engine when using module_args. Tasks executed with check mode (--check-mode) do not properly neutralize sensitive data exposed in the event data. This flaw allows unauthorized users to read this data. The highest threat from this vulnerability is to confidentiality.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
ansiblePyPI
< 2.8.142.8.14
ansiblePyPI
>= 2.9.0a1, < 2.9.122.9.12
ansiblePyPI
>= 2.10.0a1, < 2.10.1rc22.10.1rc2

Affected products

1

Patches

3
714cd2ad2eff

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

https://github.com/ansible/ansibleSloane HertelAug 27, 2020via ghsa
4 files changed · +98 2
  • changelogs/fragments/copy-sanitize-check-mode-invocation-args.yaml+7 0 added
    @@ -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)
    
  • lib/ansible/plugins/action/copy.py+7 2 modified
    @@ -209,6 +209,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"
    @@ -218,8 +220,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
     
    
  • test/integration/targets/copy/tasks/main.yml+2 0 modified
    @@ -74,6 +74,8 @@
         - import_tasks: acls.yml
           when: ansible_system == 'Linux'
     
    +    - import_tasks: no_log.yml
    +
         - import_tasks: check_mode.yml
     
         # https://github.com/ansible/ansible/issues/57618
    
  • test/integration/targets/copy/tasks/no_log.yml+82 0 added
    @@ -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 }}"
    
291f94934c8c

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

https://github.com/ansible/ansibleSloane HertelAug 7, 2020via ghsa
4 files changed · +98 2
  • changelogs/fragments/copy-sanitize-check-mode-invocation-args.yaml+7 0 added
    @@ -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)
    
  • lib/ansible/plugins/action/copy.py+7 2 modified
    @@ -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"
    @@ -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
     
    
  • test/integration/targets/copy/tasks/main.yml+2 0 modified
    @@ -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:
    
  • test/integration/targets/copy/tasks/no_log.yml+82 0 added
    @@ -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 }}"
    
6cae9a4b168d

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

https://github.com/ansible/ansibleSloane HertelAug 7, 2020via ghsa
4 files changed · +98 2
  • changelogs/fragments/copy-sanitize-check-mode-invocation-args.yaml+7 0 added
    @@ -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)
    
  • lib/ansible/plugins/action/copy.py+7 2 modified
    @@ -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"
    @@ -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
     
    
  • test/integration/targets/copy/tasks/main.yml+2 0 modified
    @@ -74,6 +74,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:
    
  • test/integration/targets/copy/tasks/no_log.yml+82 0 added
    @@ -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 }}"
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

12

News mentions

0

No linked articles in our index yet.