CVE-2018-25051: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: A vulnerability, which was classified as problematic, was found in JmPotato Pomash. This affects an unknown part of the file Pomash/theme/clean/templates/editor.html. The manipulation of the argument article.title/content.title/article.tag leads to cross site scripting. It is possible to initiate the attack remotely. The name of the patch is be1914ef0a6808e00f51618b2de92496a3604415. It is recommended to apply a patch to fix this issue. The identifier VDB-216957 was assigned to this vulnerability.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2022-12-28T12:15Z
Repository: https://github.com/JmPotato/Pomash
Language: HTML
Files changed: Pomash/libs/handler.py, Pomash/theme/clean/templates/editor.html, Pomash/theme/clean/templates/page.html
Commit date: 2018-12-29 22:07:04 +0800
Commit message: Prevent from XSS

Diff: diff --git a/Pomash/libs/handler.py b/Pomash/libs/handler.py
index 69fe8a7..0b27945 100755
--- a/Pomash/libs/handler.py
+++ b/Pomash/libs/handler.py
@@ -3,18 +3,23 @@
 
 import re
 import mistune
 import tornado.web
 
-
 from urllib.parse import unquote, quote
 
 from .models import *
 from .markdown import *
-from tornado.escape import to_unicode
+from tornado.escape import to_unicode, xhtml_escape
 
 class BaseHandler(tornado.web.RequestHandler):
+    def get_pure_title(self, title):
+        return re.sub('''<("[^"]*"|'[^']*'|[^'">])*>''', "", title).strip()
+
+    def escape_string(self, s):
+        return xhtml_escape(s)
+        
     def description(self, text):
         if len(text) <= 200:
             return re.sub('(<.*?>)', '', text).replace('\n', ' ')[:int(len(text)/2-4)] + '...'
         elif len(text) > 200:
             return re.sub('(<.*?>)', '', text).replace('\n', ' ')[:195] + '...'
diff --git a/Pomash/theme/clean/templates/editor.html b/Pomash/theme/clean/templates/editor.html
index 7c82f37..d723aa3 100755
--- a/Pomash/theme/clean/templates/editor.html
+++ b/Pomash/theme/clean/templates/editor.html
@@ -62,15 +62,15 @@
     <h1 id="title">Editor</h1>
     <article>
         <form action="#" method="post" id="article_editor">
             <div class="input">
                 <label for="title">Title</label>
-                <input id="title" name="title" type="text" value="{% if not is_page and not new %}{{ article.title }}{% elif is_page and not new %}{{ content.title }}{% end %}" style="width:100%;">
+                <input id="title" name="title" type="text" value="{% if not is_page and not new %}{{ handler.escape_string(article.title) }}{% elif is_page and not new %}{{ handler.escape_string(content.title) }}{% end %}" style="width:100%;">
             </div>
             <div v-if="!is_page" class="input">
                 <label for="tag">Tag</label>
-                <input id="tag" name="tag" type="text" value="{% if not is_page and not new %}{{ article.tag }}{% end %}" style="width:100%;">
+                <input id="tag" name="tag" type="text" value="{% if not is_page and not new %}{{ handler.escape_string(article.tag) }}{% end %}" style="width:100%;">
             </div>
             <div class="input">
                 <label for="content">Content</label>
                 <textarea :value="input" @input="update" rows="30" id="content" name="content" onkeyup="AutoSave(this);"  onchange="AutoSave(this);"ondblclick="AutoLoad(this);"></textarea>
                 <label>Tip: Double click box to load last autosave content</label>
diff --git a/Pomash/theme/clean/templates/page.html b/Pomash/theme/clean/templates/page.html
index dd95296..14c58f2 100755
--- a/Pomash/theme/clean/templates/page.html
+++ b/Pomash/theme/clean/templates/page.html
@@ -1,8 +1,24 @@
 {% extends 'layout.html' %}
 
-{% block title %} | {{ article.title }}{% end %}
+{% block title %} | {{ handler.get_pure_title(article.title) }}{% end %}
+
+{% block head %}
+    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/katex.min.css" integrity="sha384-9eLZqc9ds8eNjO3TmqPeYcDj8n+Qfa4nuSiGYa6DjLNcv9BtN69ZIulL9+8CqC9Y" crossorigin="anonymous">
+    <script defer src="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/katex.min.js" integrity="sha384-K3vbOmF2BtaVai+Qk37uypf7VrgBubhQreNQe9aGsz9lB63dIFiQVlJbr92dw2Lx" crossorigin="anonymous"></script>
+    <script defer src="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/contrib/auto-render.min.js" integrity="sha384-kmZOZB5ObwgQnS/DuDg6TScgOiWWBiVt0plIRkZCmE6rDZGrEOQeHM5PcHi+nyqe" crossorigin="anonymous"></script>
+    <script>
+        document.addEventListener("DOMContentLoaded", function() {
+            renderMathInElement(document.getElementById("article"), {
+                delimiters: [
+                    {left: "$$", right: "$$", display: true},
+                    {left: "$", right: "$", display: false}
+                ]
+            });
+        });
+    </script>
+{% end %}
 
 {% block content %}
 <div class="post">
     <h1 id="title">{{ article.title }}</h1>
     <article>

Vulnerable code: 
from tornado.escape import to_unicode
                <input id="title" name="title" type="text" value="{% if not is_page and not new %}{{ article.title }}{% elif is_page and not new %}{{ content.title }}{% end %}" style="width:100%;">
                <input id="tag" name="tag" type="text" value="{% if not is_page and not new %}{{ article.tag }}{% end %}" style="width:100%;">
{% block title %} | {{ article.title }}{% end %}
Fixed code: from tornado.escape import to_unicode, xhtml_escape
    def get_pure_title(self, title):
        return re.sub('''<("[^"]*"|'[^']*'|[^'">])*>''', "", title).strip()

    def escape_string(self, s):
        return xhtml_escape(s)
        
                <input id="title" name="title" type="text" value="{% if not is_page and not new %}{{ handler.escape_string(article.title) }}{% elif is_page and not new %}{{ handler.escape_string(content.title) }}{% end %}" style="width:100%;">
                <input id="tag" name="tag" type="text" value="{% if not is_page and not new %}{{ handler.escape_string(article.tag) }}{% end %}" style="width:100%;">
{% block title %} | {{ handler.get_pure_title(article.title) }}{% end %}

{% block head %}
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/katex.min.css" integrity="sha384-9eLZqc9ds8eNjO3TmqPeYcDj8n+Qfa4nuSiGYa6DjLNcv9BtN69ZIulL9+8CqC9Y" crossorigin="anonymous">
    <script defer src="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/katex.min.js" integrity="sha384-K3vbOmF2BtaVai+Qk37uypf7VrgBubhQreNQe9aGsz9lB63dIFiQVlJbr92dw2Lx" crossorigin="anonymous"></script>
    <script defer src="https://cdn.jsdelivr.net/npm/katex@0.10.0/dist/contrib/auto-render.min.js" integrity="sha384-kmZOZB5ObwgQnS/DuDg6TScgOiWWBiVt0plIRkZCmE6rDZGrEOQeHM5PcHi+nyqe" crossorigin="anonymous"></script>
    <script>
        document.addEventListener("DOMContentLoaded", function() {
            renderMathInElement(document.getElementById("article"), {
                delimiters: [
                    {left: "$$", right: "$$", display: true},
                    {left: "$", right: "$", display: false}
                ]
            });
        });
    </script>
{% end %}