Browse code

fix unsafe preservation across newlines (#74960) (#74975)

CVE-2021-3583
ensure we always have unsafe

Co-authored-by: Rick Elrod <rick@elrod.me>
(cherry picked from commit 4c8c40fd3d4a58defdc80e7d22aa8d26b731353e)

Brian Coca authored on 2021/06/12 06:43:22
Showing 4 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+security_fixes:
1
+  - templating engine fix for not preserving usnafe status when trying to preserve newlines. CVE-2021-3583
... ...
@@ -1064,7 +1064,8 @@ class Templar:
1064 1064
 
1065 1065
             try:
1066 1066
                 res = j2_concat(rf)
1067
-                if getattr(new_context, 'unsafe', False):
1067
+                unsafe = getattr(new_context, 'unsafe', False)
1068
+                if unsafe:
1068 1069
                     res = wrap_var(res)
1069 1070
             except TypeError as te:
1070 1071
                 if 'AnsibleUndefined' in to_native(te):
... ...
@@ -1094,6 +1095,8 @@ class Templar:
1094 1094
                 res_newlines = _count_newlines_from_end(res)
1095 1095
                 if data_newlines > res_newlines:
1096 1096
                     res += self.environment.newline_sequence * (data_newlines - res_newlines)
1097
+                    if unsafe:
1098
+                        res = wrap_var(res)
1097 1099
             return res
1098 1100
         except (UndefinedError, AnsibleUndefinedVariable) as e:
1099 1101
             if fail_on_undefined:
... ...
@@ -34,3 +34,7 @@ ansible-playbook 6653.yml -v "$@"
34 34
 
35 35
 # https://github.com/ansible/ansible/issues/72262
36 36
 ansible-playbook 72262.yml -v "$@"
37
+
38
+# ensure unsafe is preserved, even with extra newlines
39
+ansible-playbook unsafe.yml -v "$@"
40
+
37 41
new file mode 100644
... ...
@@ -0,0 +1,19 @@
0
+- hosts: localhost
1
+  gather_facts: false
2
+  vars:
3
+    nottemplated: this should not be seen
4
+    imunsafe: !unsafe '{{ nottemplated }}'
5
+  tasks:
6
+
7
+    - set_fact:
8
+        this_was_unsafe: >
9
+          {{ imunsafe }}
10
+
11
+    - set_fact:
12
+          this_always_safe: '{{ imunsafe }}'
13
+
14
+    - name: ensure nothing was templated
15
+      assert:
16
+        that:
17
+        - this_always_safe == imunsafe
18
+        - imunsafe == this_was_unsafe.strip()