changeset 8357:abf1297e7a94

bug(security): fix XSS exploit in devel and responsive templates Replace all occurances of: tal:content="structure context/MUMBLE/plain" with tal:content="context/MUMBLE/plain" This seems to have been an old way to handle display of a field when the user did not have edit rights. It does not occur in current (later than 2009) classic tracker templates. But probably was unsed in earlier classic templates since devel, reponsive and the roundup issue tracker templates were based on classic. Add CVE placeholder to security.txt and link to fix directions added to upgrading.txt. Add note in announcement.txt and CHANGES.txt Add a details element around the table of contents in the upgrading guide. It was getting long. Updated a missed XSS issue in the roundup tracker template. Live site is already fixed. XSS bug reported by 4bug of ChaMd5 Security Team H1 Group
author John Rouillard <rouilj@ieee.org>
date Tue, 08 Jul 2025 13:38:08 -0400
parents 63390dcfcfe9
children a50af46803f0
files CHANGES.txt doc/announcement.txt doc/security.txt doc/upgrading.txt share/roundup/templates/devel/html/bug.item.html share/roundup/templates/devel/html/milestone.item.html share/roundup/templates/devel/html/task.item.html share/roundup/templates/responsive/html/bug.item.html share/roundup/templates/responsive/html/milestone.item.html share/roundup/templates/responsive/html/task.item.html website/issues/html/issue.item.html
diffstat 11 files changed, 132 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES.txt	Tue Jul 08 10:23:09 2025 -0400
+++ b/CHANGES.txt	Tue Jul 08 13:38:08 2025 -0400
@@ -98,6 +98,8 @@
   Rouillard)
 - fix potential HTTP Response Splitting issue in
   roundup-server. Discovered by CodeQL in CI. (John Rouillard)
+- XSS issue in devel and responsive templates. Reported by 4bug of
+  ChaMd5 Security Team H1 Group. (John Rouillard).
 
 Features:
 
--- a/doc/announcement.txt	Tue Jul 08 10:23:09 2025 -0400
+++ b/doc/announcement.txt	Tue Jul 08 13:38:08 2025 -0400
@@ -4,7 +4,7 @@
 <https://www.roundup-tracker.org/docs/upgrading.html>`_ to
 bring your tracker up to date.
 
-The 41 changes, as usual, include some new features and many
+The 42 changes, as usual, include some new features and many
 bug fixes.
 
 Version 2.5.0 does not support Python 2. The minimum Python
@@ -28,6 +28,13 @@
 Among the significant enhancements in version 2.5.0 compared to
 the 2.4.0 release are:
 
+* **XSS vulnerability with devel and responsive templates fixed**
+
+  Just before release an XSS security issue with trackers based on
+  the devel or responsive templates was discovered. The updating
+  directions include instructions on fixing this issue with the
+  html templates.
+
 * **The property/field advanced search expression feature has been
   enhanced and documented.**
 
--- a/doc/security.txt	Tue Jul 08 10:23:09 2025 -0400
+++ b/doc/security.txt	Tue Jul 08 13:38:08 2025 -0400
@@ -28,6 +28,10 @@
 CVE Announcements
 -----------------
 
+  * `CVE-2025-pending`_ - :ref:`XSS security issue with devel or
+    responsive templates <CVE-2025-pending>`. Fixed in release 2.5.0,
+    directions available for fixing trackers based on these templates.
+
   * `CVE-2024-39124`_ - :ref:`classhelpers (_generic.help.html) are
     vulnerable to an XSS attack. <CVE-2024-39124>` Requires fixing
     tracker homes.
@@ -39,6 +43,8 @@
     executed. <CVE-2024-39126>` Fixed in release 2.4.0, directions
     available for fixing in prior versions.
 
+.. _CVE-2025-pending:
+        https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-pending
 .. _CVE-2024-39124:
         https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-39124
 .. _CVE-2024-39125:
--- a/doc/upgrading.txt	Tue Jul 08 10:23:09 2025 -0400
+++ b/doc/upgrading.txt	Tue Jul 08 13:38:08 2025 -0400
@@ -91,16 +91,101 @@
   lists.sourceforge.net). Version 2.3.0 is the last version to support
   XHTML.
 
-Contents:
+.. raw:: html
+
+  <details>
+  <summary>Contents:</summary>
 
 .. contents::
    :local:
 
+.. raw:: html
+
+  </details>
+
 .. index:: Upgrading; 2.4.0 to 2.5.0
 
 Migrating from 2.4.0 to 2.5.0
 =============================
 
+.. _CVE-2025-pending:
+
+XSS security issue with devel and responsive templates (required)
+-----------------------------------------------------------------
+
+The devel and responsive templates prior to Roundup 2.5 used this
+construct::
+
+  tal:content="structure context/MUMBLE/plain"
+
+Where ``MUMBLE`` is a property of your issues (e.g. title).
+
+This construct allows a URL with a carefully crafted query parameter
+to execute arbitrary JavaScript.
+
+You should check all your trackers.  The classic template has not used
+this construct since at least 2009, but your tracker's templates may
+use the offending construct anyway.
+
+This fix will apply if your tracker is based on the responsive or
+devel template. Check the TEMPLATE-INFO.txt file in your tracker
+home. The template name is the first component of the ``Name``
+field. For example a Name like::
+
+   Name: responsive-bugtracker
+
+   Name: devel-bugtracker
+
+shows that tracker is based on the responsive or devel templates.
+
+.. _cve-2025-pending-fixed:
+
+To fix this, remove the ``structure`` declaration when it is used with
+a plain representation. So fixing the code by replacing the example
+above with::
+
+  tal:content="context/MUMBLE/plain"
+
+prevents the attack.
+
+To check for this issue, search for ``structure`` followed by
+``/plain`` in all your html templates. If you are on a Linux/Unix
+system you can search the html subdirectory of your tracker with the
+following::
+
+   grep 'structure.*/plain' *.html
+
+which should return any lines with issues.
+
+.. warning::
+
+   Backup the files in the ``html`` subdirectory of your tracker in case
+   an edit goes wrong.
+
+You can fix this issue using the GNU sed command::
+
+  sed -i.bak -e '/structure.*\/plain/s/structure.//' *.html
+
+to edit the files in place and remove the structure keyword. It will
+create a ``.bak`` file with the original contents of the file. If you
+are on windows, some text editors support search and replace using a
+regular expression.
+
+If the construct is split across lines::
+
+     tal:content="structure
+              context/MUMBLE/plain"
+
+the commands above will miss the construct. So you should also search
+the html files using ``grep /plain *.html`` and verify that all of the
+``context/MUMBLE/plain`` include ``tal:content`` as in the `fixed
+example above <#cve-2025-pending-fixed>`_. Any lines that have
+``context/MUMBLE/plain`` without ``tal:content=`` before it need to be
+manually verified/fixed.
+
+The distributed devel and responsive templates do not split the
+construct across lines, but if you changed the files it may be split.
+
 Deprecation Notices (required)
 ------------------------------
 
--- a/share/roundup/templates/devel/html/bug.item.html	Tue Jul 08 10:23:09 2025 -0400
+++ b/share/roundup/templates/devel/html/bug.item.html	Tue Jul 08 13:38:08 2025 -0400
@@ -45,7 +45,7 @@
  <td colspan="3" tal:condition="context/title/is_edit_ok"
      tal:content="structure python:context.title.field(size=40)">title</td>
  <td colspan="3" tal:condition="not:context/title/is_edit_ok">
-  <span tal:content="structure context/title/plain"/>
+  <span tal:content="context/title/plain"/>
   <input type="hidden" name="title" tal:attributes="value context/title">
  </td>
 </tr>
--- a/share/roundup/templates/devel/html/milestone.item.html	Tue Jul 08 10:23:09 2025 -0400
+++ b/share/roundup/templates/devel/html/milestone.item.html	Tue Jul 08 13:38:08 2025 -0400
@@ -28,7 +28,7 @@
       </td>
       <td colspan="5"
           tal:condition="python: not request.user.hasPermission('Edit')"
-          tal:content="structure context/title/plain">
+          tal:content="context/title/plain">
         title
       </td>
     </tr>
@@ -54,7 +54,7 @@
       </td>
       <td colspan="5"
           tal:condition="python: not request.user.hasPermission('Edit')"
-          tal:content="structure context/status/plain">
+          tal:content="context/status/plain">
         status
       </td>
     </tr>
--- a/share/roundup/templates/devel/html/task.item.html	Tue Jul 08 10:23:09 2025 -0400
+++ b/share/roundup/templates/devel/html/task.item.html	Tue Jul 08 13:38:08 2025 -0400
@@ -45,7 +45,7 @@
  <td colspan="3" tal:condition="context/title/is_edit_ok"
      tal:content="structure python:context.title.field(size=60)">title</td>
  <td colspan="3" tal:condition="not:context/title/is_edit_ok">
-  <span tal:content="structure context/title/plain"/>
+  <span tal:content="context/title/plain"/>
   <input type="hidden" name="title" tal:attributes="value context/title">
  </td>
 </tr>
--- a/share/roundup/templates/responsive/html/bug.item.html	Tue Jul 08 10:23:09 2025 -0400
+++ b/share/roundup/templates/responsive/html/bug.item.html	Tue Jul 08 13:38:08 2025 -0400
@@ -42,13 +42,13 @@
         <div class='container-fluid' tal:condition="not:context/is_edit_ok">
           <dl class='dl-horizontal'>
             <dt i18n:translate="">Title</dt>
-            <dd tal:content="structure context/title/plain"></dd>
+            <dd tal:content="context/title/plain"></dd>
             <dt i18n:translate="">Type</dt>
-            <dd tal:content="structure context/type/plain"></dd>
+            <dd tal:content="context/type/plain"></dd>
             <dt i18n:translate="">Components</dt>
-            <dd tal:content="structure context/components/plain"></dd>
+            <dd tal:content="context/components/plain"></dd>
             <dt i18n:translate="">Version</dt>
-            <dd tal:content="structure context/versions/plain"></dd>
+            <dd tal:content="context/versions/plain"></dd>
           </dl>
         </div>
         <div class='container-fluid' tal:condition="context/is_edit_ok">
@@ -126,23 +126,23 @@
           <div class='row-fluid'>
             <dl class='dl-horizontal span6'>
               <dt i18n:translate="">Status</dt>
-              <dd tal:content="structure context/status/plain"></dd>
+              <dd tal:content="context/status/plain"></dd>
               <dt i18n:translate="">Resolution</dt>
-              <dd tal:content="structure context/resolution/plain"></dd>
+              <dd tal:content="context/resolution/plain"></dd>
               <dt i18n:translate="">Dependencies</dt>
-              <dd tal:content="structure context/dependencies/plain"></dd>
+              <dd tal:content="context/dependencies/plain"></dd>
               <dt i18n:translate="">Superseder</dt>
-              <dd tal:content="structure context/superseder/plain"></dd>
+              <dd tal:content="context/superseder/plain"></dd>
             </dl>
             <dl class='dl-horizontal span6'>
               <dt i18n:translate="">Assigned to</dt>
-              <dd tal:content="structure context/assignee/plain"></dd>
+              <dd tal:content="context/assignee/plain"></dd>
               <dt i18n:translate="">Nosy list</dt>
-              <dd tal:content="structure context/nosy/plain"></dd>
+              <dd tal:content="context/nosy/plain"></dd>
               <dt i18n:translate="">Priority</dt>
-              <dd tal:content="structure context/priority/plain"></dd>
+              <dd tal:content="context/priority/plain"></dd>
               <dt i18n:translate="">Keywords</dt>
-              <dd tal:content="structure context/keywords/plain"></dd>
+              <dd tal:content="context/keywords/plain"></dd>
             </dl>
           </div>
         </div>
--- a/share/roundup/templates/responsive/html/milestone.item.html	Tue Jul 08 10:23:09 2025 -0400
+++ b/share/roundup/templates/responsive/html/milestone.item.html	Tue Jul 08 13:38:08 2025 -0400
@@ -24,7 +24,7 @@
       </td>
       <td colspan="5"
           tal:condition="python: not request.user.hasPermission('Edit')"
-          tal:content="structure context/title/plain">
+          tal:content="context/title/plain">
         title
       </td>
     </tr>
@@ -50,7 +50,7 @@
       </td>
       <td colspan="5"
           tal:condition="python: not request.user.hasPermission('Edit')"
-          tal:content="structure context/status/plain">
+          tal:content="context/status/plain">
         status
       </td>
     </tr>
--- a/share/roundup/templates/responsive/html/task.item.html	Tue Jul 08 10:23:09 2025 -0400
+++ b/share/roundup/templates/responsive/html/task.item.html	Tue Jul 08 13:38:08 2025 -0400
@@ -43,11 +43,11 @@
         <div class='container-fluid' tal:condition="not:context/is_edit_ok">
           <dl class='dl-horizontal'>
             <dt i18n:translate="">Title</dt>
-            <dd tal:content="structure context/title/plain"></dd>
+            <dd tal:content="context/title/plain"></dd>
             <dt i18n:translate="">Type</dt>
-            <dd tal:content="structure context/type/plain"></dd>
+            <dd tal:content="context/type/plain"></dd>
             <dt i18n:translate="">Components</dt>
-            <dd tal:content="structure context/components/plain"></dd>
+            <dd tal:content="context/components/plain"></dd>
           </dl>
         </div>
         <div class='container-fluid' tal:condition="context/is_edit_ok">
@@ -61,7 +61,7 @@
           <div class='control-group vspace-two' tal:condition="not:context/title/is_edit_ok">
             <label class='control-label' i18n:translate="">Title</label>
             <div class='controls'>
-              <span class='input-xxlarge uneditable-input' tal:content="structure context/title/plain"></span>
+              <span class='input-xxlarge uneditable-input' tal:content="context/title/plain"></span>
             </div>
           </div>
 
@@ -102,21 +102,21 @@
           <div class='row-fluid'>
             <dl class='dl-horizontal span6'>
               <dt i18n:translate="">Status</dt>
-              <dd tal:content="structure context/status/plain"></dd>
+              <dd tal:content="context/status/plain"></dd>
               <dt i18n:translate="">Resolution</dt>
-              <dd tal:content="structure context/resolution/plain"></dd>
+              <dd tal:content="context/resolution/plain"></dd>
               <dt i18n:translate="">Dependencies</dt>
-              <dd tal:content="structure context/dependencies/plain"></dd>
+              <dd tal:content="context/dependencies/plain"></dd>
               <dt i18n:translate="">Superseder</dt>
-              <dd tal:content="structure context/superseder/plain"></dd>
+              <dd tal:content="context/superseder/plain"></dd>
             </dl>
             <dl class='dl-horizontal span6'>
               <dt i18n:translate="">Assigned to</dt>
-              <dd tal:content="structure context/assignee/plain"></dd>
+              <dd tal:content="context/assignee/plain"></dd>
               <dt i18n:translate="">Nosy list</dt>
-              <dd tal:content="structure context/nosy/plain"></dd>
+              <dd tal:content="context/nosy/plain"></dd>
               <dt i18n:translate="">Priority</dt>
-              <dd tal:content="structure context/priority/plain"></dd>
+              <dd tal:content="context/priority/plain"></dd>
             </dl>
           </div>
         </div>
--- a/website/issues/html/issue.item.html	Tue Jul 08 10:23:09 2025 -0400
+++ b/website/issues/html/issue.item.html	Tue Jul 08 13:38:08 2025 -0400
@@ -127,7 +127,7 @@
   </select>
  </td>
  <td tal:condition="not:context/assignee/is_edit_ok">
-  <span tal:replace="structure context/assignee/plain" />
+  <span tal:replace="context/assignee/plain" />
  </td>
  <th><label for="nosy" i18n:translate="">Nosy List</label>:
   <span tal:condition="context/nosy/is_edit_ok"

Roundup Issue Tracker: http://roundup-tracker.org/