VYPR
High severityNVD Advisory· Published Jul 13, 2018· Updated Aug 5, 2024

CVE-2018-10875

CVE-2018-10875

Description

A flaw was found in ansible. ansible.cfg is read from the current working directory which can be altered to make it point to a plugin or a module path under the control of an attacker, thus allowing the attacker to execute arbitrary code.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Ansible loads ansible.cfg from the current working directory, allowing local attackers to execute arbitrary code by controlling plugin/module paths.

Vulnerability

A flaw in Ansible allows the configuration file ansible.cfg to be read from the current working directory when executing ad-hoc commands or playbooks. This behavior can be exploited if an attacker places a malicious ansible.cfg in a directory where a victim runs Ansible, pointing to attacker-controlled plugin or module paths. Affected versions include Ansible prior to the security updates that restrict configuration loading from world-writable directories [1][2].

Exploitation

An attacker with local access to a system can create a crafted ansible.cfg in a directory where a victim later executes an Ansible command. The attacker does not require any special privileges beyond write access to that directory. When the victim runs Ansible in that directory, the malicious configuration causes Ansible to load plugins or modules from attacker-controlled paths, leading to arbitrary code execution [1][3].

Impact

Successful exploitation allows the attacker to execute arbitrary code with the privileges of the user running Ansible. This can result in information disclosure, privilege escalation, or full system compromise, depending on the context [1][3].

Mitigation

The vulnerability is fixed in Ansible 2.5.5 and later, and in corresponding updates from vendors such as Red Hat and Ubuntu [2][4]. Users should update to the latest version. As a workaround, ensure that Ansible is not executed in directories writable by untrusted users, and consider using a dedicated configuration file location via the ANSIBLE_CONFIG environment variable.

AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
ansiblePyPI
< 2.4.6.02.4.6.0
ansiblePyPI
>= 2.5.0a1, < 2.5.62.5.6
ansiblePyPI
>= 2.6.0a1, < 2.6.12.6.1

Affected products

148

Patches

3
ff980afefdbe

[stable-2.5] ignore ansible.cfg in world writable cwd (#42070) (#42142)

https://github.com/ansible/ansibleToshio KuratomiJul 3, 2018via ghsa
5 files changed · +38 10
  • changelogs/fragments/wrcwd_ansible.cfg.yml+2 0 added
    @@ -0,0 +1,2 @@
    +bugfixes:
    +  - '**Security Fix** - avoid using ansible.cfg in a world writable dir.'
    
  • docs/docsite/rst/installation_guide/intro_configuration.rst+2 2 modified
    @@ -21,7 +21,7 @@ The stock configuration should be sufficient for most users, but there may be re
     .. _getting_the_latest_configuration:
     
     Getting the latest configuration
    -================================
    +--------------------------------
     
     If installing Ansible from a package manager, the latest ansible.cfg file should be present in /etc/ansible, possibly
     as a ".rpmnew" file (or other) as appropriate in the case of updates.
    @@ -35,6 +35,7 @@ For more details and a full listing of available configurations go to :ref:`conf
     
     For in-depth details, see :ref:`ansible_configuration_settings`.
     
    +.. _environmental_configuration:
     
     Environmental configuration
     ===========================
    @@ -55,4 +56,3 @@ Settings in the command line will override those passed through the configuratio
     
     The full list of options available is in :ref:`ansible-playbook` and :ref:`ansible`.
     
    -
    
  • docs/templates/man.j2+8 4 modified
    @@ -76,17 +76,18 @@ ENVIRONMENT
     The following environment variables may be specified.
     
     {% if inventory %}
    -ANSIBLE_INVENTORY  -- Override the default ansible inventory file
    +ANSIBLE_INVENTORY  -- Override the default ansible inventory sources
     
     {% endif %}
     {% if library %}
     ANSIBLE_LIBRARY -- Override the default ansible module library path
     
     {% endif %}
    -ANSIBLE_CONFIG -- Override the default ansible config file
    +ANSIBLE_CONFIG -- Specify override location for the ansible config file
     
     Many more are available for most options in ansible.cfg
     
    +For a full list check https://docs.ansible.com/. or use the `ansible-config` command.
     
     FILES
     -----
    @@ -99,6 +100,9 @@ FILES
     
     ~/.ansible.cfg -- User config file, overrides the default config if present
     
    +./ansible.cfg -- Local config file (in current working direcotry) assumed to be 'project specific' and overrides the rest if present.
    +
    +As mentioned above, the ANSIBLE_CONFIG environment variable will override all others.
     
     AUTHOR
     ------
    @@ -109,8 +113,8 @@ Ansible was originally written by Michael DeHaan.
     COPYRIGHT
     ---------
     
    -Copyright © 2017 Red Hat, Inc | Ansible.
    -Ansible is released under the terms of the GPLv3 License.
    +Copyright © 2018 Red Hat, Inc | Ansible.
    +Ansible is released under the terms of the GPLv3 license.
     
     
     SEE ALSO
    
  • lib/ansible/config/manager.py+12 3 modified
    @@ -6,6 +6,7 @@
     
     import os
     import sys
    +import stat
     import tempfile
     
     from collections import namedtuple
    @@ -139,7 +140,7 @@ def get_ini_config_value(p, entry):
         return value
     
     
    -def find_ini_config_file():
    +def find_ini_config_file(warnings=None):
         ''' Load INI Config File order(first found is used): ENV, CWD, HOME, /etc/ansible '''
         # FIXME: eventually deprecate ini configs
     
    @@ -149,7 +150,14 @@ def find_ini_config_file():
             if os.path.isdir(path0):
                 path0 += "/ansible.cfg"
         try:
    -        path1 = os.getcwd() + "/ansible.cfg"
    +        path1 = os.getcwd()
    +        perms1 = os.stat(path1)
    +        if perms1.st_mode & stat.S_IWOTH:
    +            if warnings is not None:
    +                warnings.add("Ansible is in a world writable directory (%s), ignoring it as an ansible.cfg source." % to_text(path1))
    +            path1 = None
    +        else:
    +            path1 += "/ansible.cfg"
         except OSError:
             path1 = None
         path2 = unfrackpath("~/.ansible.cfg", follow=False)
    @@ -168,6 +176,7 @@ class ConfigManager(object):
     
         UNABLE = []
         DEPRECATED = []
    +    WARNINGS = set()
     
         def __init__(self, conf_file=None, defs_file=None):
     
    @@ -193,7 +202,7 @@ def __init__(self, conf_file=None, defs_file=None):
     
             if self._config_file is None:
                 # set config using ini
    -            self._config_file = find_ini_config_file()
    +            self._config_file = find_ini_config_file(self.WARNINGS)
     
             # consume configuration
             if self._config_file:
    
  • lib/ansible/constants.py+14 1 modified
    @@ -17,14 +17,24 @@
     from ansible.config.manager import ConfigManager, ensure_type, get_ini_config_value
     
     
    +def _warning(msg):
    +    ''' display is not guaranteed here, nor it being the full class, but try anyways, fallback to sys.stderr.write '''
    +    try:
    +        from __main__ import display
    +        display.warning(msg)
    +    except:
    +        import sys
    +        sys.stderr.write(' [WARNING] %s\n' % (msg))
    +
    +
     def _deprecated(msg, version='2.8'):
         ''' display is not guaranteed here, nor it being the full class, but try anyways, fallback to sys.stderr.write '''
         try:
             from __main__ import display
             display.deprecated(msg, version=version)
         except:
             import sys
    -        sys.stderr.write('[DEPRECATED] %s, to be removed in %s' % (msg, version))
    +        sys.stderr.write(' [DEPRECATED] %s, to be removed in %s\n' % (msg, version))
     
     
     def mk_boolean(value):
    @@ -186,3 +196,6 @@ def set_constant(name, value, export=vars()):
             value = ensure_type(value, setting.name)
     
         set_constant(setting.name, value)
    +
    +for warn in config.WARNINGS:
    +    _warning(warn)
    
f32c42c37aaf

[stable-2.4] ignore ansible.cfg in world writable cwd (#42070)

https://github.com/ansible/ansibleBrian CocaJun 29, 2018via ghsa
4 files changed · +35 7
  • CHANGELOG.md+2 0 modified
    @@ -8,6 +8,8 @@ Ansible Changes By Release
     ### Bugfixes
     * **Security Fix** - avoid loading host/group vars from cwd when not specifying
       a playbook or playbook base dir (https://github.com/ansible/ansible/pull/42067)
    +* **Security Fix** - avoid using ansible.cfg in a world readable dir
    +  https://github.com/ansible/ansible/pull/42070
     
     
     <a id="2.4.5"></a>
    
  • docs/templates/man.j2+8 4 modified
    @@ -76,17 +76,18 @@ ENVIRONMENT
     The following environment variables may be specified.
     
     {% if inventory %}
    -ANSIBLE_INVENTORY  -- Override the default ansible inventory file
    +ANSIBLE_INVENTORY  -- Override the default ansible inventory sources
     
     {% endif %}
     {% if library %}
     ANSIBLE_LIBRARY -- Override the default ansible module library path
     
     {% endif %}
    -ANSIBLE_CONFIG -- Override the default ansible config file
    +ANSIBLE_CONFIG -- Specify override location for the ansible config file
     
     Many more are available for most options in ansible.cfg
     
    +For a full list check https://docs.ansible.com/. or use the `ansible-config` command.
     
     FILES
     -----
    @@ -99,6 +100,9 @@ FILES
     
     ~/.ansible.cfg -- User config file, overrides the default config if present
     
    +./ansible.cfg -- Local config file (in current working direcotry) assumed to be 'project specific' and overrides the rest if present.
    +
    +As mentioned above, the ANSIBLE_CONFIG environment variable will override all others.
     
     AUTHOR
     ------
    @@ -110,8 +114,8 @@ See the AUTHORS file for a complete list of contributors.
     COPYRIGHT
     ---------
     
    -Copyright © 2017 Red Hat, Inc | Ansible.
    -Ansible is released under the terms of the GPLv3 License.
    +Copyright © 2018 Red Hat, Inc | Ansible.
    +Ansible is released under the terms of the GPLv3 license.
     
     
     SEE ALSO
    
  • lib/ansible/config/manager.py+12 3 modified
    @@ -7,6 +7,7 @@
     
     import os
     import sys
    +import stat
     import tempfile
     import yaml
     
    @@ -134,7 +135,7 @@ def get_ini_config_value(p, entry):
         return value
     
     
    -def find_ini_config_file():
    +def find_ini_config_file(warnings=None):
         ''' Load INI Config File order(first found is used): ENV, CWD, HOME, /etc/ansible '''
         # FIXME: eventually deprecate ini configs
     
    @@ -144,7 +145,14 @@ def find_ini_config_file():
             if os.path.isdir(path0):
                 path0 += "/ansible.cfg"
         try:
    -        path1 = os.getcwd() + "/ansible.cfg"
    +        path1 = os.getcwd()
    +        perms1 = os.stat(path1)
    +        if perms1.st_mode & stat.S_IWOTH:
    +            if warnings is not None:
    +                warnings.add("Ansible is in a world writable directory (%s), ignoring it as an ansible.cfg source." % to_text(path1))
    +            path1 = None
    +        else:
    +            path1 += "/ansible.cfg"
         except OSError:
             path1 = None
         path2 = unfrackpath("~/.ansible.cfg", follow=False)
    @@ -163,6 +171,7 @@ class ConfigManager(object):
     
         UNABLE = []
         DEPRECATED = []
    +    WARNINGS = set()
     
         def __init__(self, conf_file=None):
     
    @@ -184,7 +193,7 @@ def __init__(self, conf_file=None):
     
             if self._config_file is None:
                 # set config using ini
    -            self._config_file = find_ini_config_file()
    +            self._config_file = find_ini_config_file(self.WARNINGS)
     
             if self._config_file:
                 if os.path.exists(self._config_file):
    
  • lib/ansible/constants.py+13 0 modified
    @@ -18,6 +18,16 @@
     from ansible.config.manager import ConfigManager, ensure_type, get_ini_config_value
     
     
    +def _warning(msg):
    +    ''' display is not guaranteed here, nor it being the full class, but try anyways, fallback to sys.stderr.write '''
    +    try:
    +        from __main__ import display
    +        display.warning(msg)
    +    except:
    +        import sys
    +        sys.stderr.write(' [WARNING] %s\n' % (msg))
    +
    +
     def _deprecated(msg):
         ''' display is not guaranteed here, nor it being the full class, but try anyways, fallback to sys.stderr.write '''
         try:
    @@ -122,3 +132,6 @@ def set_constant(name, value, export=vars()):
             value = ensure_type(value, setting.name)
     
         set_constant(setting.name, value)
    +
    +for warn in config.WARNINGS:
    +    _warning(warn)
    
4cecbe81adbc

[stable-2.6] ignore ansible.cfg in world writable cwd (#42070)

https://github.com/ansible/ansibleBrian CocaJun 29, 2018via ghsa
5 files changed · +38 10
  • changelogs/fragments/wrcwd_ansible.cfg.yml+2 0 added
    @@ -0,0 +1,2 @@
    +bugfixes:
    +  - '**Security Fix** - avoid using ansible.cfg in a world writable dir.'
    
  • docs/docsite/rst/installation_guide/intro_configuration.rst+2 2 modified
    @@ -22,7 +22,7 @@ Paths where configuration file is searched are listed in :ref:`reference documen
     .. _getting_the_latest_configuration:
     
     Getting the latest configuration
    -================================
    +--------------------------------
     
     If installing Ansible from a package manager, the latest ansible.cfg file should be present in /etc/ansible, possibly
     as a ".rpmnew" file (or other) as appropriate in the case of updates.
    @@ -36,6 +36,7 @@ For more details and a full listing of available configurations go to :ref:`conf
     
     For in-depth details, see :ref:`ansible_configuration_settings`.
     
    +.. _environmental_configuration:
     
     Environmental configuration
     ===========================
    @@ -56,4 +57,3 @@ Settings in the command line will override those passed through the configuratio
     
     The full list of options available is in :ref:`ansible-playbook` and :ref:`ansible`.
     
    -
    
  • docs/templates/man.j2+8 4 modified
    @@ -76,17 +76,18 @@ ENVIRONMENT
     The following environment variables may be specified.
     
     {% if inventory %}
    -ANSIBLE_INVENTORY  -- Override the default ansible inventory file
    +ANSIBLE_INVENTORY  -- Override the default ansible inventory sources
     
     {% endif %}
     {% if library %}
     ANSIBLE_LIBRARY -- Override the default ansible module library path
     
     {% endif %}
    -ANSIBLE_CONFIG -- Override the default ansible config file
    +ANSIBLE_CONFIG -- Specify override location for the ansible config file
     
     Many more are available for most options in ansible.cfg
     
    +For a full list check https://docs.ansible.com/. or use the `ansible-config` command.
     
     FILES
     -----
    @@ -99,6 +100,9 @@ FILES
     
     ~/.ansible.cfg -- User config file, overrides the default config if present
     
    +./ansible.cfg -- Local config file (in current working direcotry) assumed to be 'project specific' and overrides the rest if present.
    +
    +As mentioned above, the ANSIBLE_CONFIG environment variable will override all others.
     
     AUTHOR
     ------
    @@ -109,8 +113,8 @@ Ansible was originally written by Michael DeHaan.
     COPYRIGHT
     ---------
     
    -Copyright © 2017 Red Hat, Inc | Ansible.
    -Ansible is released under the terms of the GPLv3 License.
    +Copyright © 2018 Red Hat, Inc | Ansible.
    +Ansible is released under the terms of the GPLv3 license.
     
     
     SEE ALSO
    
  • lib/ansible/config/manager.py+12 3 modified
    @@ -6,6 +6,7 @@
     
     import os
     import sys
    +import stat
     import tempfile
     
     from collections import namedtuple
    @@ -141,7 +142,7 @@ def get_ini_config_value(p, entry):
         return value
     
     
    -def find_ini_config_file():
    +def find_ini_config_file(warnings=None):
         ''' Load INI Config File order(first found is used): ENV, CWD, HOME, /etc/ansible '''
         # FIXME: eventually deprecate ini configs
     
    @@ -151,7 +152,14 @@ def find_ini_config_file():
             if os.path.isdir(path0):
                 path0 += "/ansible.cfg"
         try:
    -        path1 = os.getcwd() + "/ansible.cfg"
    +        path1 = os.getcwd()
    +        perms1 = os.stat(path1)
    +        if perms1.st_mode & stat.S_IWOTH:
    +            if warnings is not None:
    +                warnings.add("Ansible is in a world writable directory (%s), ignoring it as an ansible.cfg source." % to_text(path1))
    +            path1 = None
    +        else:
    +            path1 += "/ansible.cfg"
         except OSError:
             path1 = None
         path2 = unfrackpath("~/.ansible.cfg", follow=False)
    @@ -170,6 +178,7 @@ class ConfigManager(object):
     
         UNABLE = {}
         DEPRECATED = []
    +    WARNINGS = set()
     
         def __init__(self, conf_file=None, defs_file=None):
     
    @@ -195,7 +204,7 @@ def __init__(self, conf_file=None, defs_file=None):
     
             if self._config_file is None:
                 # set config using ini
    -            self._config_file = find_ini_config_file()
    +            self._config_file = find_ini_config_file(self.WARNINGS)
     
             # consume configuration
             if self._config_file:
    
  • lib/ansible/constants.py+14 1 modified
    @@ -17,14 +17,24 @@
     from ansible.config.manager import ConfigManager, ensure_type, get_ini_config_value
     
     
    +def _warning(msg):
    +    ''' display is not guaranteed here, nor it being the full class, but try anyways, fallback to sys.stderr.write '''
    +    try:
    +        from __main__ import display
    +        display.warning(msg)
    +    except:
    +        import sys
    +        sys.stderr.write(' [WARNING] %s\n' % (msg))
    +
    +
     def _deprecated(msg, version='2.8'):
         ''' display is not guaranteed here, nor it being the full class, but try anyways, fallback to sys.stderr.write '''
         try:
             from __main__ import display
             display.deprecated(msg, version=version)
         except:
             import sys
    -        sys.stderr.write('[DEPRECATED] %s, to be removed in %s' % (msg, version))
    +        sys.stderr.write(' [DEPRECATED] %s, to be removed in %s\n' % (msg, version))
     
     
     def mk_boolean(value):
    @@ -189,3 +199,6 @@ def set_constant(name, value, export=vars()):
             value = ensure_type(value, setting.type)
     
         set_constant(setting.name, value)
    +
    +for warn in config.WARNINGS:
    +    _warning(warn)
    

Vulnerability mechanics

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

References

25

News mentions

0

No linked articles in our index yet.