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

CVE-2018-10874

CVE-2018-10874

Description

In ansible it was found that inventory variables are loaded from current working directory when running ad-hoc command which are under attacker's control, allowing to run arbitrary code as a result.

AI Insight

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

Ansible ad-hoc commands load inventory variables from the current working directory, allowing an attacker to run arbitrary code by placing a crafted file.

Vulnerability

Ansible versions prior to the fix are affected by a vulnerability where ansible.cfg and inventory variables are loaded from the current working directory when running ad-hoc commands. This behavior allows an attacker to control the configuration file or inventory variables if they can place a crafted file in the directory where the command is executed [1][2][3][4].

Exploitation

A local attacker with the ability to write or place a malicious ansible.cfg or inventory file in the current working directory can influence the behavior of an ad-hoc command. When a user runs an ad-hoc command from that directory, the system loads the attacker-controlled configuration or variables, referencing arbitrary plugin or module paths, leading to code execution [1][4].

Impact

Successful exploitation allows the attacker to run arbitrary code with the privileges of the user running the ad-hoc command, resulting in local privilege escalation and potential system compromise [1][4].

Mitigation

The vulnerability is fixed in Ansible versions released after the disclosure. Red Hat has issued fixes via RHSA-2018:2321, and Ubuntu has released updates as part of USN-4072-1 [3][4]. Users should update to the latest patched version. No workaround is documented; the recommended mitigation is to apply the patch or ensure ad-hoc commands are not run from untrusted directories.

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, < 2.5.62.5.6
ansiblePyPI
>= 2.6, < 2.6.12.6.1

Affected products

37

Patches

3
10d6fe6c98cf

[stable-2.5] avoid loading vars on unspecified basedir (cwd) (#42067) (#42139)

https://github.com/ansible/ansibleToshio KuratomiJul 3, 2018via ghsa
3 files changed · +15 2
  • changelogs/fragments/avoid_cwd_vars.yml+2 0 added
    @@ -0,0 +1,2 @@
    +bugfixes:
    +    - '**Security Fix** - avoid loading host/group vars from cwd when not specifying a playbook or playbook base dir'
    
  • lib/ansible/cli/__init__.py+7 1 modified
    @@ -662,7 +662,7 @@ def version_info(gitinfo=False):
                     ansible_versions[counter] = 0
                 try:
                     ansible_versions[counter] = int(ansible_versions[counter])
    -            except:
    +            except Exception:
                     pass
             if len(ansible_versions) < 3:
                 for counter in range(len(ansible_versions), 3):
    @@ -807,6 +807,12 @@ def _play_prereqs(options):
             # the code, ensuring a consistent view of global variables
             variable_manager = VariableManager(loader=loader, inventory=inventory)
     
    +        if hasattr(options, 'basedir'):
    +            if options.basedir:
    +                variable_manager.safe_basedir = True
    +        else:
    +            variable_manager.safe_basedir = True
    +
             # load vars from cli options
             variable_manager.extra_vars = load_extra_vars(loader=loader, options=options)
             variable_manager.options_vars = load_options_vars(options, CLI.version_info(gitinfo=False))
    
  • lib/ansible/vars/manager.py+6 1 modified
    @@ -90,6 +90,7 @@ def __init__(self, loader=None, inventory=None):
             self._hostvars = None
             self._omit_token = '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest()
             self._options_vars = defaultdict(dict)
    +        self.safe_basedir = False
     
             # bad cache plugin is not fatal error
             try:
    @@ -110,6 +111,7 @@ def __getstate__(self):
                 omit_token=self._omit_token,
                 options_vars=self._options_vars,
                 inventory=self._inventory,
    +            safe_basedir=self.safe_basedir,
             )
             return data
     
    @@ -123,6 +125,7 @@ def __setstate__(self, data):
             self._omit_token = data.get('omit_token', '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest())
             self._inventory = data.get('inventory', None)
             self._options_vars = data.get('options_vars', dict())
    +        self.safe_basedir = data.get('safe_basedir', False)
     
         @property
         def extra_vars(self):
    @@ -183,7 +186,9 @@ def get_vars(self, play=None, host=None, task=None, include_hostvars=True, inclu
             )
     
             # default for all cases
    -        basedirs = [self._loader.get_basedir()]
    +        basedirs = []
    +        if self.safe_basedir:  # avoid adhoc/console loading cwd
    +            basedirs = [self._loader.get_basedir()]
     
             if play:
                 # first we compile any vars specified in defaults/main.yml
    
44874addc7ea

[stable-2.4] avoid loading vars on unspecified basedir (cwd) (#42067)

https://github.com/ansible/ansibleBrian CocaJun 29, 2018via ghsa
3 files changed · +16 3
  • CHANGELOG.md+3 1 modified
    @@ -3,9 +3,11 @@ Ansible Changes By Release
     
     <a id="2.4.6"></a>
     
    -## 2.4.5 "Dancing Days" - TBD
    +## 2.4.6 "Dancing Days" - TBD
     
     ### Bugfixes
    +* **Security Fix** - avoid using ansible.cfg in a world readable dir
    +  https://github.com/ansible/ansible/pull/42070
     
     
     <a id="2.4.5"></a>
    
  • lib/ansible/cli/__init__.py+7 1 modified
    @@ -652,7 +652,7 @@ def version_info(gitinfo=False):
                     ansible_versions[counter] = 0
                 try:
                     ansible_versions[counter] = int(ansible_versions[counter])
    -            except:
    +            except Exception:
                     pass
             if len(ansible_versions) < 3:
                 for counter in range(len(ansible_versions), 3):
    @@ -793,6 +793,12 @@ def _play_prereqs(options):
             # the code, ensuring a consistent view of global variables
             variable_manager = VariableManager(loader=loader, inventory=inventory)
     
    +        if hasattr(options, 'basedir'):
    +            if options.basedir:
    +                variable_manager.safe_basedir = True
    +        else:
    +            variable_manager.safe_basedir = True
    +
             # load vars from cli options
             variable_manager.extra_vars = load_extra_vars(loader=loader, options=options)
             variable_manager.options_vars = load_options_vars(options, CLI.version_info(gitinfo=False))
    
  • lib/ansible/vars/manager.py+6 1 modified
    @@ -122,6 +122,7 @@ def __init__(self, loader=None, inventory=None):
             self._hostvars = None
             self._omit_token = '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest()
             self._options_vars = defaultdict(dict)
    +        self.safe_basedir = False
     
             # bad cache plugin is not fatal error
             try:
    @@ -142,6 +143,7 @@ def __getstate__(self):
                 omit_token=self._omit_token,
                 options_vars=self._options_vars,
                 inventory=self._inventory,
    +            safe_basedir=self.safe_basedir,
             )
             return data
     
    @@ -155,6 +157,7 @@ def __setstate__(self, data):
             self._omit_token = data.get('omit_token', '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest())
             self._inventory = data.get('inventory', None)
             self._options_vars = data.get('options_vars', dict())
    +        self.safe_basedir = data.get('safe_basedir', False)
     
         @property
         def extra_vars(self):
    @@ -233,7 +236,9 @@ def get_vars(self, play=None, host=None, task=None, include_hostvars=True, inclu
             )
     
             # default for all cases
    -        basedirs = [self._loader.get_basedir()]
    +        basedirs = []
    +        if self.safe_basedir:  # avoid adhoc/console loading cwd
    +            basedirs = [self._loader.get_basedir()]
     
             if play:
                 # first we compile any vars specified in defaults/main.yml
    
1f80949f964a

[stable-2.6] avoid loading vars on unspecified basedir (cwd) (#42067)

https://github.com/ansible/ansibleBrian CocaJun 29, 2018via ghsa
3 files changed · +15 2
  • changelogs/fragments/avoid_cwd_vars.yml+2 0 added
    @@ -0,0 +1,2 @@
    +bugfixes:
    +    - '**Security Fix** - avoid loading host/group vars from cwd when not specifying a playbook or playbook base dir'
    
  • lib/ansible/cli/__init__.py+7 1 modified
    @@ -664,7 +664,7 @@ def version_info(gitinfo=False):
                     ansible_versions[counter] = 0
                 try:
                     ansible_versions[counter] = int(ansible_versions[counter])
    -            except:
    +            except Exception:
                     pass
             if len(ansible_versions) < 3:
                 for counter in range(len(ansible_versions), 3):
    @@ -809,6 +809,12 @@ def _play_prereqs(options):
             # the code, ensuring a consistent view of global variables
             variable_manager = VariableManager(loader=loader, inventory=inventory)
     
    +        if hasattr(options, 'basedir'):
    +            if options.basedir:
    +                variable_manager.safe_basedir = True
    +        else:
    +            variable_manager.safe_basedir = True
    +
             # load vars from cli options
             variable_manager.extra_vars = load_extra_vars(loader=loader, options=options)
             variable_manager.options_vars = load_options_vars(options, CLI.version_info(gitinfo=False))
    
  • lib/ansible/vars/manager.py+6 1 modified
    @@ -90,6 +90,7 @@ def __init__(self, loader=None, inventory=None):
             self._hostvars = None
             self._omit_token = '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest()
             self._options_vars = defaultdict(dict)
    +        self.safe_basedir = False
     
             # bad cache plugin is not fatal error
             try:
    @@ -110,6 +111,7 @@ def __getstate__(self):
                 omit_token=self._omit_token,
                 options_vars=self._options_vars,
                 inventory=self._inventory,
    +            safe_basedir=self.safe_basedir,
             )
             return data
     
    @@ -123,6 +125,7 @@ def __setstate__(self, data):
             self._omit_token = data.get('omit_token', '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest())
             self._inventory = data.get('inventory', None)
             self._options_vars = data.get('options_vars', dict())
    +        self.safe_basedir = data.get('safe_basedir', False)
     
         @property
         def extra_vars(self):
    @@ -183,7 +186,9 @@ def get_vars(self, play=None, host=None, task=None, include_hostvars=True, inclu
             )
     
             # default for all cases
    -        basedirs = [self._loader.get_basedir()]
    +        basedirs = []
    +        if self.safe_basedir:  # avoid adhoc/console loading cwd
    +            basedirs = [self._loader.get_basedir()]
     
             if play:
                 # first we compile any vars specified in defaults/main.yml
    

Vulnerability mechanics

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

References

22

News mentions

0

No linked articles in our index yet.