You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by ju...@apache.org on 2026/09/25 14:45:20 UTC

(jspwiki) 16/33: JSPWIKI-1292 see jira for details

This is an automated email from the ASF dual-hosted git repository.

juanpablo-santos pushed a commit to branch master-2.x
in repository https://gitbox.apache.org/repos/asf/jspwiki.git

commit ff06e4996004ba27e74ee32c2432f4b308759fff
Author: Alex O'Ree <al...@apache.org>
AuthorDate: Sun Aug 23 12:17:12 2026 -0400

    JSPWIKI-1292 see jira for details
---
 .../apache/wiki/parser/JSPWikiMarkupParser.java    |  4 ++--
 .../java/org/apache/wiki/parser/PluginContent.java |  7 ++++--
 .../wiki/render/WysiwygEditingRendererTest.java    | 26 ++++++++++++++++++++++
 .../main/webapp/templates/210/editors/CKeditor.jsp |  2 +-
 .../main/webapp/templates/210/editors/TinyMCE.jsp  |  2 +-
 .../webapp/templates/default/editors/CKeditor.jsp  |  2 +-
 .../webapp/templates/default/editors/TinyMCE.jsp   |  2 +-
 .../webapp/templates/default/editors/wysiwyg.jsp   |  2 +-
 8 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/jspwiki-main/src/main/java/org/apache/wiki/parser/JSPWikiMarkupParser.java b/jspwiki-main/src/main/java/org/apache/wiki/parser/JSPWikiMarkupParser.java
index 0998f6068..982def0aa 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/parser/JSPWikiMarkupParser.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/parser/JSPWikiMarkupParser.java
@@ -787,7 +787,7 @@ public class JSPWikiMarkupParser extends MarkupParser {
 
     private Element handleAccessRule( String ruleLine ) {
         if( m_wysiwygEditorMode ) {
-            m_currentElement.addContent( "[" + ruleLine + "]" );
+            m_currentElement.addContent( "[" + TextUtil.escapeHTMLEntities( ruleLine ) + "]" );
         }
         if( !m_parseAccessRules ) {
             return m_currentElement;
@@ -821,7 +821,7 @@ public class JSPWikiMarkupParser extends MarkupParser {
      */
     private Element handleMetadata( final String link ) {
         if( m_wysiwygEditorMode ) {
-            m_currentElement.addContent( "[" + link + "]" );
+            m_currentElement.addContent( "[" + TextUtil.escapeHTMLEntities( link ) + "]" );
         }
 
         try {
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/parser/PluginContent.java b/jspwiki-main/src/main/java/org/apache/wiki/parser/PluginContent.java
index ae121de88..63f718cf1 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/parser/PluginContent.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/parser/PluginContent.java
@@ -32,6 +32,7 @@ import org.apache.wiki.api.plugin.Plugin;
 import org.apache.wiki.api.plugin.PluginElement;
 import org.apache.wiki.plugin.PluginManager;
 import org.apache.wiki.preferences.Preferences;
+import org.apache.wiki.util.TextUtil;
 import org.apache.wiki.variables.VariableManager;
 import org.jdom2.Text;
 
@@ -147,8 +148,10 @@ public class PluginContent extends Text implements PluginElement {
             if( wysiwygEditorMode && !m_pluginName.matches( EMITTABLE_PLUGINS ) ) {
                 result = PLUGIN_START + m_pluginName + SPACE;
 
-                // convert newlines to <br> in case the plugin has a body.
-                final String cmdLine = m_params.get( CMDLINE ).replaceAll( LINEBREAK, ELEMENT_BR );
+                // escape the raw command line first: this text node is emitted with output escaping
+                // disabled, so unescaped markup would reach the wysiwyg editor (and its <textarea>)
+                // as live HTML.  Then convert newlines to <br> in case the plugin has a body.
+                final String cmdLine = TextUtil.escapeHTMLEntities( m_params.get( CMDLINE ) ).replaceAll( LINEBREAK, ELEMENT_BR );
                 result = result + cmdLine + PLUGIN_END;
             } else {
                 final Boolean b = context.getVariable( Context.VAR_EXECUTE_PLUGINS );
diff --git a/jspwiki-main/src/test/java/org/apache/wiki/render/WysiwygEditingRendererTest.java b/jspwiki-main/src/test/java/org/apache/wiki/render/WysiwygEditingRendererTest.java
index dadf54f6f..67736f3e7 100644
--- a/jspwiki-main/src/test/java/org/apache/wiki/render/WysiwygEditingRendererTest.java
+++ b/jspwiki-main/src/test/java/org/apache/wiki/render/WysiwygEditingRendererTest.java
@@ -49,8 +49,15 @@ public class WysiwygEditingRendererTest {
     }
 
     private String render( final String s ) throws IOException {
+        return render( s, false );
+    }
+
+    private String render( final String s, final boolean wysiwygEditorMode ) throws IOException {
         final Page dummyPage = Wiki.contents().page(testEngine,"TestPage");
         final Context ctx = Wiki.context().create(testEngine,dummyPage);
+        if( wysiwygEditorMode ) {
+            ctx.setVariable( Context.VAR_WYSIWYG_EDITOR_MODE, Boolean.TRUE );
+        }
 
         final StringReader in = new StringReader(s);
 
@@ -92,4 +99,23 @@ public class WysiwygEditingRendererTest {
         Assertions.assertEquals( "<a class=\"createpage\" href=\"Non-existent Pagename with Spaces\">Non-existent Pagename with Spaces</a>", render(src) );
     }
 
+    /**
+     * The wysiwyg render path echoes raw plugin command lines, access rules and metadata back into the
+     * generated HTML with output escaping disabled.  Unescaped markup there breaks out of the wysiwyg
+     * editors' &lt;textarea&gt; (stored XSS).  See the textarea sinks in templates/editors/*.jsp.
+     */
+    @Test
+    public void testWysiwygEchoedMarkupIsEscaped() throws Exception {
+        final String payload = "</textarea><script>alert(1)</script>";
+
+        String html = render( "[{SomePlugin " + payload + "}]", true );
+        Assertions.assertFalse( html.contains( payload ), html );
+
+        html = render( "[{SET foo='" + payload + "'}]", true );
+        Assertions.assertFalse( html.contains( payload ), html );
+
+        html = render( "[{ALLOW edit " + payload + "}]", true );
+        Assertions.assertFalse( html.contains( payload ), html );
+    }
+
 }
diff --git a/jspwiki-war/src/main/webapp/templates/210/editors/CKeditor.jsp b/jspwiki-war/src/main/webapp/templates/210/editors/CKeditor.jsp
index d4bac805b..cb679ada4 100644
--- a/jspwiki-war/src/main/webapp/templates/210/editors/CKeditor.jsp
+++ b/jspwiki-war/src/main/webapp/templates/210/editors/CKeditor.jsp
@@ -167,7 +167,7 @@
       </fieldset>
     </wiki:CheckRequestContext>
 
-    <textarea name="htmlPageText"><%=pageAsHtml%></textarea>
+    <textarea name="htmlPageText"><%=pageAsHtml.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")%></textarea>
 </form>
 <script type="text/javascript">
 //<![CDATA[
diff --git a/jspwiki-war/src/main/webapp/templates/210/editors/TinyMCE.jsp b/jspwiki-war/src/main/webapp/templates/210/editors/TinyMCE.jsp
index 008876c7e..6abdb0b0e 100644
--- a/jspwiki-war/src/main/webapp/templates/210/editors/TinyMCE.jsp
+++ b/jspwiki-war/src/main/webapp/templates/210/editors/TinyMCE.jsp
@@ -163,7 +163,7 @@
       </fieldset>
     </wiki:CheckRequestContext>
 
-    <textarea name="htmlPageText"><%=pageAsHtml%></textarea>
+    <textarea name="htmlPageText"><%=pageAsHtml.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")%></textarea>
 </form>
 <script type="text/javascript">
 //<![CDATA[
diff --git a/jspwiki-war/src/main/webapp/templates/default/editors/CKeditor.jsp b/jspwiki-war/src/main/webapp/templates/default/editors/CKeditor.jsp
index 6a973858f..c737989a1 100644
--- a/jspwiki-war/src/main/webapp/templates/default/editors/CKeditor.jsp
+++ b/jspwiki-war/src/main/webapp/templates/default/editors/CKeditor.jsp
@@ -255,7 +255,7 @@
   <div class="row edit-area livepreview previewcolumn"><%-- .livepreview  .previewcolumn--%>
       <div>
         <textarea name="htmlPageText"
-             autofocus="autofocus"><%=pageAsHtml.replace("&", "&amp;")%></textarea>
+             autofocus="autofocus"><%=pageAsHtml.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")%></textarea>
       </div>
       <div class="ajaxpreview" >Preview comes here</div>
   </div>
diff --git a/jspwiki-war/src/main/webapp/templates/default/editors/TinyMCE.jsp b/jspwiki-war/src/main/webapp/templates/default/editors/TinyMCE.jsp
index ec156fa62..3070b58b0 100644
--- a/jspwiki-war/src/main/webapp/templates/default/editors/TinyMCE.jsp
+++ b/jspwiki-war/src/main/webapp/templates/default/editors/TinyMCE.jsp
@@ -259,7 +259,7 @@
   <div class="row edit-area livepreview previewcolumn"><%-- .livepreview  .previewcolumn--%>
       <div>
         <textarea name="htmlPageText"
-             autofocus="autofocus"><%=pageAsHtml.replace("&", "&amp;")%></textarea>
+             autofocus="autofocus"><%=pageAsHtml.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")%></textarea>
       </div>
       <div class="ajaxpreview" >Preview comes here</div>
   </div>
diff --git a/jspwiki-war/src/main/webapp/templates/default/editors/wysiwyg.jsp b/jspwiki-war/src/main/webapp/templates/default/editors/wysiwyg.jsp
index 2c4617a50..14049c8ff 100644
--- a/jspwiki-war/src/main/webapp/templates/default/editors/wysiwyg.jsp
+++ b/jspwiki-war/src/main/webapp/templates/default/editors/wysiwyg.jsp
@@ -257,7 +257,7 @@
         To avoid this, double escape the & char =>  so &amp;lt; is converted to &lt;
         --%>
         <textarea name="htmlPageText"
-             autofocus="autofocus"><%= pageAsHtml.replace("&", "&amp;")%></textarea>
+             autofocus="autofocus"><%= pageAsHtml.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")%></textarea>
       </div>
       <div class="ajaxpreview">Preview comes here</div>
   </div>