浏览代码

[Dovecot] Use Jinja2 sandbox for rendering quota and quarantine notifications

FreddleSpl0it 2 月之前
父节点
当前提交
2fbbbbe9a9
共有 3 个文件被更改,包括 32 次插入18 次删除
  1. 16 10
      data/Dockerfiles/dovecot/quarantine_notify.py
  2. 15 7
      data/Dockerfiles/dovecot/quota_notify.py
  3. 1 1
      docker-compose.yml

+ 16 - 10
data/Dockerfiles/dovecot/quarantine_notify.py

@@ -8,7 +8,8 @@ from email.mime.multipart import MIMEMultipart
 from email.mime.text import MIMEText
 from email.utils import COMMASPACE, formatdate
 import jinja2
-from jinja2 import Template
+from jinja2 import TemplateError
+from jinja2.sandbox import SandboxedEnvironment
 import json
 import redis
 import time
@@ -80,17 +81,22 @@ try:
     if len(meta_query) == 0:
       return
     msg_count = len(meta_query)
+    env = SandboxedEnvironment()
     if r.get('Q_HTML'):
-      try:
-        template = Template(r.get('Q_HTML'))
-      except:
-        print("Error: Cannot parse quarantine template, falling back to default template.")
-        with open('/templates/quarantine.tpl') as file_:
-          template = Template(file_.read())
+        try:
+            template = env.from_string(r.get('Q_HTML'))
+        except Exception:
+            print("Error: Cannot parse quarantine template, falling back to default template.")
+            with open('/templates/quarantine.tpl') as file_:
+                template = env.from_string(file_.read())
     else:
-      with open('/templates/quarantine.tpl') as file_:
-        template = Template(file_.read())
-    html = template.render(meta=meta_query, username=rcpt, counter=msg_count, hostname=mailcow_hostname, quarantine_acl=quarantine_acl)
+        with open('/templates/quarantine.tpl') as file_:
+            template = env.from_string(file_.read())
+    try:
+        html = template.render(meta=meta_query, username=rcpt, counter=msg_count, hostname=mailcow_hostname, quarantine_acl=quarantine_acl)
+    except (jinja2.exceptions.SecurityError, TemplateError) as ex:
+        print(f"SecurityError or TemplateError in template rendering: {ex}")
+        return
     text = html2text.html2text(html)
     count = 0
     while count < 15:

+ 15 - 7
data/Dockerfiles/dovecot/quota_notify.py

@@ -6,7 +6,7 @@ from email.mime.multipart import MIMEMultipart
 from email.mime.text import MIMEText
 from email.utils import COMMASPACE, formatdate
 import jinja2
-from jinja2 import Template
+from jinja2.sandbox import SandboxedEnvironment
 import redis
 import time
 import json
@@ -33,16 +33,24 @@ while True:
 
 if r.get('QW_HTML'):
   try:
-    template = Template(r.get('QW_HTML'))
-  except:
-    print("Error: Cannot parse quarantine template, falling back to default template.")
+    env = SandboxedEnvironment()
+    template = env.from_string(r.get('QW_HTML'))
+  except Exception:
+    print("Error: Cannot parse quota template, falling back to default template.")
     with open('/templates/quota.tpl') as file_:
-      template = Template(file_.read())
+      env = SandboxedEnvironment()
+      template = env.from_string(file_.read())
 else:
   with open('/templates/quota.tpl') as file_:
-    template = Template(file_.read())
+    env = SandboxedEnvironment()
+    template = env.from_string(file_.read())
+
+try:
+  html = template.render(username=username, percent=percent)
+except (jinja2.exceptions.SecurityError, jinja2.TemplateError) as ex:
+  print(f"SecurityError or TemplateError in template rendering: {ex}")
+  sys.exit(1)
 
-html = template.render(username=username, percent=percent)
 text = html2text.html2text(html)
 
 try:

+ 1 - 1
docker-compose.yml

@@ -251,7 +251,7 @@ services:
             - sogo
 
     dovecot-mailcow:
-      image: ghcr.io/mailcow/dovecot:2.33
+      image: ghcr.io/mailcow/dovecot:2.34
       depends_on:
         - mysql-mailcow
         - netfilter-mailcow