Skip to content

Commit

Permalink
Prevent failures due to unsafe plugin name (#82759)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkrizek committed Mar 6, 2024
1 parent b65a6cd commit 56f3112
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 0 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/82708-unsafe-plugin-name-error.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bugfixes:
- "Fix an issue when setting a plugin name from an unsafe source resulted in ``ValueError: unmarshallable object`` (https://github.com/ansible/ansible/issues/82708)"
12 changes: 12 additions & 0 deletions lib/ansible/plugins/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from ansible.utils.collection_loader._collection_finder import _AnsibleCollectionFinder, _get_collection_metadata
from ansible.utils.display import Display
from ansible.utils.plugin_docs import add_fragments
from ansible.utils.unsafe_proxy import _is_unsafe

# TODO: take the packaging dep, or vendor SpecifierSet?

Expand Down Expand Up @@ -862,6 +863,17 @@ def get(self, name, *args, **kwargs):

def get_with_context(self, name, *args, **kwargs):
''' instantiates a plugin of the given name using arguments '''
if _is_unsafe(name):
# Objects constructed using the name wrapped as unsafe remain
# (correctly) unsafe. Using such unsafe objects in places
# where underlying types (builtin string in this case) are
# expected can cause problems.
# One such case is importlib.abc.Loader.exec_module failing
# with "ValueError: unmarshallable object" because the module
# object is created with the __path__ attribute being wrapped
# as unsafe which isn't marshallable.
# Manually removing the unsafe wrapper prevents such issues.
name = name._strip_unsafe()

found_in_cache = True
class_only = kwargs.pop('class_only', False)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from ansible.plugins.action import ActionBase


class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=None):
return {"nca_executed": True}
2 changes: 2 additions & 0 deletions test/integration/targets/plugin_loader/runme.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ ansible-playbook use_coll_name.yml -i ../../inventory -e 'ansible_connection=ans

# test filter loading ignoring duplicate file basename
ansible-playbook file_collision/play.yml "$@"

ANSIBLE_COLLECTIONS_PATH=$PWD/collections ansible-playbook unsafe_plugin_name.yml "$@"
9 changes: 9 additions & 0 deletions test/integration/targets/plugin_loader/unsafe_plugin_name.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
- hosts: localhost
gather_facts: false
tasks:
- action: !unsafe n.c.a
register: r

- assert:
that:
- r.nca_executed

0 comments on commit 56f3112

Please sign in to comment.