summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelogs/fragments/77535-prevent-losing-unsafe-lookups.yml2
-rw-r--r--lib/ansible/template/__init__.py12
-rw-r--r--test/integration/targets/template/unsafe.yml45
-rw-r--r--test/units/template/test_templar.py25
4 files changed, 81 insertions, 3 deletions
diff --git a/changelogs/fragments/77535-prevent-losing-unsafe-lookups.yml b/changelogs/fragments/77535-prevent-losing-unsafe-lookups.yml
new file mode 100644
index 0000000000..14ae6f2fed
--- /dev/null
+++ b/changelogs/fragments/77535-prevent-losing-unsafe-lookups.yml
@@ -0,0 +1,2 @@
+bugfixes:
+ - Prevent losing unsafe on results returned from lookups (https://github.com/ansible/ansible/issues/77535)
diff --git a/lib/ansible/template/__init__.py b/lib/ansible/template/__init__.py
index 5006c035d4..00cfa00671 100644
--- a/lib/ansible/template/__init__.py
+++ b/lib/ansible/template/__init__.py
@@ -1107,15 +1107,19 @@ class Templar:
jvars = AnsibleJ2Vars(self, t.globals)
- self.cur_context = new_context = t.new_context(jvars, shared=True)
- rf = t.root_render_func(new_context)
+ # In case this is a recursive call to do_template we need to
+ # save/restore cur_context to prevent overriding __UNSAFE__.
+ cached_context = self.cur_context
+
+ self.cur_context = t.new_context(jvars, shared=True)
+ rf = t.root_render_func(self.cur_context)
try:
if self.jinja2_native:
res = ansible_native_concat(rf)
else:
res = j2_concat(rf)
- unsafe = getattr(new_context, 'unsafe', False)
+ unsafe = getattr(self.cur_context, 'unsafe', False)
if unsafe:
res = wrap_var(res)
except TypeError as te:
@@ -1126,6 +1130,8 @@ class Templar:
else:
display.debug("failing because of a type error, template data is: %s" % to_text(data))
raise AnsibleError("Unexpected templating type error occurred on (%s): %s" % (to_native(data), to_native(te)))
+ finally:
+ self.cur_context = cached_context
if self.jinja2_native and not isinstance(res, string_types):
return res
diff --git a/test/integration/targets/template/unsafe.yml b/test/integration/targets/template/unsafe.yml
index 6746e1ea0c..bef9a4b450 100644
--- a/test/integration/targets/template/unsafe.yml
+++ b/test/integration/targets/template/unsafe.yml
@@ -17,3 +17,48 @@
that:
- this_always_safe == imunsafe
- imunsafe == this_was_unsafe.strip()
+
+
+- hosts: localhost
+ gather_facts: false
+ vars:
+ output_dir: "{{ lookup('env', 'OUTPUT_DIR') }}"
+ tasks:
+ - set_fact:
+ unsafe_foo: "{{ lookup('list', var0) }}"
+ vars:
+ var0: "{{ var1 }}"
+ var1:
+ - unsafe
+
+ - assert:
+ that:
+ - "{{ unsafe_foo[0] | type_debug == 'AnsibleUnsafeText' }}"
+
+ - block:
+ - copy:
+ dest: "{{ file_name }}"
+ content: !unsafe "{{ i_should_not_be_templated }}"
+
+ - set_fact:
+ file_content: "{{ lookup('file', file_name) }}"
+
+ - assert:
+ that:
+ - not file_content is contains('unsafe')
+
+ - set_fact:
+ file_content: "{{ lookup('file', file_name_tmpl) }}"
+ vars:
+ file_name_tmpl: "{{ file_name }}"
+
+ - assert:
+ that:
+ - not file_content is contains('unsafe')
+ vars:
+ file_name: "{{ output_dir }}/unsafe_file"
+ i_should_not_be_templated: unsafe
+ always:
+ - file:
+ dest: "{{ file_name }}"
+ state: absent
diff --git a/test/units/template/test_templar.py b/test/units/template/test_templar.py
index dd6985ce3b..181bb31e9f 100644
--- a/test/units/template/test_templar.py
+++ b/test/units/template/test_templar.py
@@ -444,3 +444,28 @@ class TestAnsibleContext(BaseTemplar, unittest.TestCase):
def test_is_unsafe(self):
context = self._context()
self.assertFalse(context._is_unsafe(AnsibleUndefined()))
+
+
+def test_unsafe_lookup():
+ res = Templar(
+ None,
+ variables={
+ 'var0': '{{ var1 }}',
+ 'var1': ['unsafe'],
+ }
+ ).template('{{ lookup("list", var0) }}')
+ assert getattr(res[0], '__UNSAFE__', False)
+
+
+def test_unsafe_lookup_no_conversion():
+ res = Templar(
+ None,
+ variables={
+ 'var0': '{{ var1 }}',
+ 'var1': ['unsafe'],
+ }
+ ).template(
+ '{{ lookup("list", var0) }}',
+ convert_data=False,
+ )
+ assert getattr(res, '__UNSAFE__', False)