You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by jl...@apache.org on 2015/11/10 14:40:22 UTC

svn commit: r1713634 - in /ofbiz/trunk: applications/content/config/ applications/content/src/org/ofbiz/content/content/ applications/order/src/org/ofbiz/order/order/ applications/order/webapp/ordermgr/entry/catalog/ applications/party/src/org/ofbiz/pa...

Author: jleroux
Date: Tue Nov 10 13:40:22 2015
New Revision: 1713634

URL: http://svn.apache.org/viewvc?rev=1713634&view=rev
Log:
Completes r1709882 for <<Possible static XSS issue with Content>> https://issues.apache.org/jira/browse/OFBIZ-6669

As explained in OFBIZ-6669 last comments, contrary to what I did in ContentWorker class, when I before did the work on *ContentWrapper classes I did not use the sanitizer but only an encoder (either HTML or URL).
Because I wrongly supposed that only plain text was used there and certainly my lazy mind thought it was easier because of the URL encoderType to also handle.

When the encoderType is HTML, we now use the sanitizer in *ContentWrapper classes, and ContentWorker.java has also been adapted. 
For that I enhanced the UtilCodec class. The sanitizer is only used when HTML is requested, else the sanitize() method simply calls the encode() method.

I removed the content.sanitize property in content.properties and added a sanitizer.permissive.policy property in the new owasp.properties (in base config) with some explanations. This allows for more configuration.

I changed the line 85 in productsummary.ftl to use an HTML content wrapper, same in minilastviewedcategories.ftl. 
To be totally complete, we should change *lines like* in productsummary.ftl line 85 to use an HTML content wrapper.
Not easy to spot but anyway those not done will simply not totally show well, without any security impacts.

Added:
    ofbiz/trunk/framework/base/config/owasp.properties   (with props)
Modified:
    ofbiz/trunk/applications/content/config/content.properties
    ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentWorker.java
    ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderContentWrapper.java
    ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/productsummary.ftl
    ofbiz/trunk/applications/party/src/org/ofbiz/party/content/PartyContentWrapper.java
    ofbiz/trunk/applications/product/src/org/ofbiz/product/category/CategoryContentWrapper.java
    ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigItemContentWrapper.java
    ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductContentWrapper.java
    ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductPromoContentWrapper.java
    ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/content/WorkEffortContentWrapper.java
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/UtilCodec.java
    ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/minilastviewedcategories.ftl

Modified: ofbiz/trunk/applications/content/config/content.properties
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/content/config/content.properties?rev=1713634&r1=1713633&r2=1713634&view=diff
==============================================================================
--- ofbiz/trunk/applications/content/config/content.properties (original)
+++ ofbiz/trunk/applications/content/config/content.properties Tue Nov 10 13:40:22 2015
@@ -34,8 +34,4 @@ content.upload.max.files=250
 content.upload.always.local.file=true
 
 # content output folder (relative to ofbiz.home)
-content.output.path=runtime/output
-
-#Should we sanitize generic content by default (specific contents - order, party, category, product, configured product, product promo and work effort - are always encoded)
-# This has a slightly impact on the code rendered, see OFBIZ-6669. True By default! 
-content.sanitize=true
+content.output.path=runtime/output
\ No newline at end of file

Modified: ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentWorker.java?rev=1713634&r1=1713633&r2=1713634&view=diff
==============================================================================
--- ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentWorker.java (original)
+++ ofbiz/trunk/applications/content/src/org/ofbiz/content/content/ContentWorker.java Tue Nov 10 13:40:22 2015
@@ -35,6 +35,7 @@ import org.ofbiz.base.util.BshUtil;
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.GeneralException;
 import org.ofbiz.base.util.StringUtil;
+import org.ofbiz.base.util.UtilCodec;
 import org.ofbiz.base.util.UtilDateTime;
 import org.ofbiz.base.util.UtilGenerics;
 import org.ofbiz.base.util.UtilMisc;
@@ -52,7 +53,6 @@ import org.ofbiz.entity.condition.Entity
 import org.ofbiz.entity.condition.EntityOperator;
 import org.ofbiz.entity.util.EntityQuery;
 import org.ofbiz.entity.util.EntityUtil;
-import org.ofbiz.entity.util.EntityUtilProperties;
 import org.ofbiz.minilang.MiniLangException;
 import org.ofbiz.minilang.SimpleMapProcessor;
 import org.ofbiz.service.DispatchContext;
@@ -60,8 +60,6 @@ import org.ofbiz.service.GenericServiceE
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.service.ModelService;
 import org.ofbiz.service.ServiceUtil;
-import org.owasp.html.PolicyFactory;
-import org.owasp.html.Sanitizers;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
@@ -74,6 +72,7 @@ import freemarker.ext.dom.NodeModel;
 public class ContentWorker implements org.ofbiz.widget.content.ContentWorkerInterface {
 
     public static final String module = ContentWorker.class.getName();
+    static final UtilCodec.SimpleEncoder encoder = UtilCodec.getEncoder("html");
 
     public ContentWorker() { }
 
@@ -339,8 +338,7 @@ public class ContentWorker implements or
         String rendered = writer.toString();
         // According to https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet#XSS_Prevention_Rules_Summary
         // Normally head should be protected by X-XSS-Protection Response Header by default
-        if (EntityUtilProperties.propertyValueEqualsIgnoreCase("content.properties", "content.sanitize", "true", delegator) 
-                && (rendered.contains("<script>")
+        if ((rendered.contains("<script>")
                 || rendered.contains("<!--")
                 || rendered.contains("<div")
                 || rendered.contains("<style>")
@@ -349,8 +347,7 @@ public class ContentWorker implements or
                 || rendered.contains("<input")
                 || rendered.contains("<iframe")
                 || rendered.contains("<a"))) {
-            PolicyFactory sanitizer = Sanitizers.FORMATTING.and(Sanitizers.BLOCKS).and(Sanitizers.IMAGES).and(Sanitizers.LINKS).and(Sanitizers.STYLES);
-            rendered = sanitizer.sanitize(rendered);
+            rendered = encoder.sanitize(rendered);
         }
         return rendered; 
     }
@@ -1256,7 +1253,7 @@ public class ContentWorker implements or
             contentAssoc = delegator.makeValue("ContentAssoc");
             try {
                 // TODO: locale needs to be gotten correctly
-                SimpleMapProcessor.runSimpleMapProcessor("component://content/script/org/ofbiz/content/ContentManagementMapProcessors.xml", "contentAssocIn", content, contentAssoc, new LinkedList(), Locale.getDefault());
+                SimpleMapProcessor.runSimpleMapProcessor("component://content/script/org/ofbiz/content/ContentManagementMapProcessors.xml", "contentAssocIn", content, contentAssoc, new LinkedList<Object>(), Locale.getDefault());
                 context.put("contentAssocTypeId", contentAssoc.get("contentAssocTypeId"));
                 context.put("contentAssocPredicateId", contentAssoc.get("contentAssocPredicateId"));
                 context.put("mapKey", contentAssoc.get("mapKey"));

Modified: ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderContentWrapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderContentWrapper.java?rev=1713634&r1=1713633&r2=1713634&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderContentWrapper.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderContentWrapper.java Tue Nov 10 13:40:22 2015
@@ -109,7 +109,7 @@ public class OrderContentWrapper impleme
             if (UtilValidate.isEmpty(outString)) {
                 outString = outString == null? "" : outString;
             }
-            outString = encoder.encode(outString);
+            outString = encoder.sanitize(outString);
             if (orderContentCache != null) {
                 orderContentCache.put(cacheKey, outString);
             }

Modified: ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/productsummary.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/productsummary.ftl?rev=1713634&r1=1713633&r2=1713634&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/productsummary.ftl (original)
+++ ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/productsummary.ftl Tue Nov 10 13:40:22 2015
@@ -82,7 +82,7 @@ ${virtualJavaScript!}
                 <img src="<@o...@ofbizContentUrl>" alt="Small Image"/><br />
                 ${uiLabelMap.ProductProductId}   : ${product.productId!}<br />
                 ${uiLabelMap.ProductProductName} : ${product.productName!}<br />
-                ${uiLabelMap.CommonDescription}  : ${product.description!}
+                ${uiLabelMap.CommonDescription}  : ${productContentWrapper.get("DESCRIPTION", "html")!}
               </td>
             </tr>
           </table>

Modified: ofbiz/trunk/applications/party/src/org/ofbiz/party/content/PartyContentWrapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/party/src/org/ofbiz/party/content/PartyContentWrapper.java?rev=1713634&r1=1713633&r2=1713634&view=diff
==============================================================================
--- ofbiz/trunk/applications/party/src/org/ofbiz/party/content/PartyContentWrapper.java (original)
+++ ofbiz/trunk/applications/party/src/org/ofbiz/party/content/PartyContentWrapper.java Tue Nov 10 13:40:22 2015
@@ -160,7 +160,7 @@ public class PartyContentWrapper impleme
                 outString = party.getModelEntity().isField(candidateFieldName) ? party.getString(candidateFieldName): "";
                 outString = outString == null? "" : outString;
             }
-            outString = encoder.encode(outString);
+            outString = encoder.sanitize(outString);
             if (partyContentCache != null) {
                 partyContentCache.put(cacheKey, outString);
             }
@@ -168,11 +168,11 @@ public class PartyContentWrapper impleme
         } catch (GeneralException e) {
             Debug.logError(e, "Error rendering PartyContent, inserting empty String", module);
             String candidateOut = party.getModelEntity().isField(candidateFieldName) ? party.getString(candidateFieldName): "";
-            return candidateOut == null? "" : encoder.encode(candidateOut);
+            return candidateOut == null? "" : encoder.sanitize(candidateOut);
         } catch (IOException e) {
             Debug.logError(e, "Error rendering PartyContent, inserting empty String", module);
             String candidateOut = party.getModelEntity().isField(candidateFieldName) ? party.getString(candidateFieldName): "";
-            return candidateOut == null? "" : encoder.encode(candidateOut);
+            return candidateOut == null? "" : encoder.sanitize(candidateOut);
         }
     }
 

Modified: ofbiz/trunk/applications/product/src/org/ofbiz/product/category/CategoryContentWrapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/product/category/CategoryContentWrapper.java?rev=1713634&r1=1713633&r2=1713634&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/product/category/CategoryContentWrapper.java (original)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/product/category/CategoryContentWrapper.java Tue Nov 10 13:40:22 2015
@@ -108,7 +108,7 @@ public class CategoryContentWrapper impl
                 outString = productCategory.getModelEntity().isField(candidateFieldName) ? productCategory.getString(candidateFieldName): "";
                 outString = outString == null? "" : outString;
             }
-            outString = encoder.encode(outString);
+            outString = encoder.sanitize(outString);
             if (categoryContentCache != null) {
                 categoryContentCache.put(cacheKey, outString);
             }

Modified: ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigItemContentWrapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigItemContentWrapper.java?rev=1713634&r1=1713633&r2=1713634&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigItemContentWrapper.java (original)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigItemContentWrapper.java Tue Nov 10 13:40:22 2015
@@ -131,7 +131,7 @@ public class ProductConfigItemContentWra
                 outString = productConfigItem.getModelEntity().isField(candidateFieldName) ? productConfigItem.getString(candidateFieldName): "";
                 outString = outString == null? "" : outString;
             }
-            outString = encoder.encode(outString);
+            outString = encoder.sanitize(outString);
             if (configItemContentCache != null) {
                 configItemContentCache.put(cacheKey, outString);
             }
@@ -139,11 +139,11 @@ public class ProductConfigItemContentWra
         } catch (GeneralException e) {
             Debug.logError(e, "Error rendering ProdConfItemContent, inserting empty String", module);
             String candidateOut = productConfigItem.getModelEntity().isField(candidateFieldName) ? productConfigItem.getString(candidateFieldName): "";
-            return candidateOut == null? "" : encoder.encode(candidateOut);
+            return candidateOut == null? "" : encoder.sanitize(candidateOut);
         } catch (IOException e) {
             Debug.logError(e, "Error rendering ProdConfItemContent, inserting empty String", module);
             String candidateOut = productConfigItem.getModelEntity().isField(candidateFieldName) ? productConfigItem.getString(candidateFieldName): "";
-            return candidateOut == null? "" : encoder.encode(candidateOut);
+            return candidateOut == null? "" : encoder.sanitize(candidateOut);
         }
     }
 

Modified: ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductContentWrapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductContentWrapper.java?rev=1713634&r1=1713633&r2=1713634&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductContentWrapper.java (original)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductContentWrapper.java Tue Nov 10 13:40:22 2015
@@ -121,7 +121,7 @@ public class ProductContentWrapper imple
                 outString = product.getModelEntity().isField(candidateFieldName) ? product.getString(candidateFieldName): "";
                 outString = outString == null? "" : outString;
             }
-            outString = encoder.encode(outString);
+            outString = encoder.sanitize(outString);
             if (productContentCache != null) {
                 productContentCache.put(cacheKey, outString);
             }
@@ -129,11 +129,11 @@ public class ProductContentWrapper imple
         } catch (GeneralException e) {
             Debug.logError(e, "Error rendering ProductContent, inserting empty String", module);
             String candidateOut = product.getModelEntity().isField(candidateFieldName) ? product.getString(candidateFieldName): "";
-            return candidateOut == null? "" : encoder.encode(candidateOut);
+            return candidateOut == null? "" : encoder.sanitize(candidateOut);
         } catch (IOException e) {
             Debug.logError(e, "Error rendering ProductContent, inserting empty String", module);
             String candidateOut = product.getModelEntity().isField(candidateFieldName) ? product.getString(candidateFieldName): "";
-            return candidateOut == null? "" : encoder.encode(candidateOut);
+            return candidateOut == null? "" : encoder.sanitize(candidateOut);
         }
     }
 

Modified: ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductPromoContentWrapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductPromoContentWrapper.java?rev=1713634&r1=1713633&r2=1713634&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductPromoContentWrapper.java (original)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductPromoContentWrapper.java Tue Nov 10 13:40:22 2015
@@ -124,7 +124,7 @@ public class ProductPromoContentWrapper
                 outString = productPromo.getModelEntity().isField(candidateFieldName) ? productPromo.getString(candidateFieldName): "";
                 outString = outString == null? "" : outString;
             }
-            outString = encoder.encode(outString);
+            outString = encoder.sanitize(outString);
             if (productPromoContentCache != null) {
                 productPromoContentCache.put(cacheKey, outString);
             }
@@ -132,11 +132,11 @@ public class ProductPromoContentWrapper
         } catch (GeneralException e) {
             Debug.logError(e, "Error rendering ProductPromoContent, inserting empty String", module);
             String candidateOut = productPromo.getModelEntity().isField(candidateFieldName) ? productPromo.getString(candidateFieldName): "";
-            return candidateOut == null? "" : encoder.encode(candidateOut);
+            return candidateOut == null? "" : encoder.sanitize(candidateOut);
         } catch (IOException e) {
             Debug.logError(e, "Error rendering ProductPromoContent, inserting empty String", module);
             String candidateOut = productPromo.getModelEntity().isField(candidateFieldName) ? productPromo.getString(candidateFieldName): "";
-            return candidateOut == null? "" : encoder.encode(candidateOut);
+            return candidateOut == null? "" : encoder.sanitize(candidateOut);
         }
     }
 

Modified: ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/content/WorkEffortContentWrapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/content/WorkEffortContentWrapper.java?rev=1713634&r1=1713633&r2=1713634&view=diff
==============================================================================
--- ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/content/WorkEffortContentWrapper.java (original)
+++ ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/content/WorkEffortContentWrapper.java Tue Nov 10 13:40:22 2015
@@ -254,7 +254,7 @@ public class WorkEffortContentWrapper im
                 outString = workEffort.getModelEntity().isField(candidateFieldName) ? workEffort.getString(candidateFieldName): "";
                 outString = outString == null? "" : outString;
             }
-            outString = encoder.encode(outString);
+            outString = encoder.sanitize(outString);
             if (workEffortContentCache != null) {
                 workEffortContentCache.put(cacheKey, outString);
             }
@@ -262,11 +262,11 @@ public class WorkEffortContentWrapper im
         } catch (GeneralException e) {
             Debug.logError(e, "Error rendering WorkEffortContent, inserting empty String", module);
             String candidateOut = workEffort.getModelEntity().isField(candidateFieldName) ? workEffort.getString(candidateFieldName): "";
-            return candidateOut == null? "" : encoder.encode(candidateOut);
+            return candidateOut == null? "" : encoder.sanitize(candidateOut);
         } catch (IOException e) {
             Debug.logError(e, "Error rendering WorkEffortContent, inserting empty String", module);
             String candidateOut = workEffort.getModelEntity().isField(candidateFieldName) ? workEffort.getString(candidateFieldName): "";
-            return candidateOut == null? "" : encoder.encode(candidateOut);
+            return candidateOut == null? "" : encoder.sanitize(candidateOut);
         }
     }
 

Added: ofbiz/trunk/framework/base/config/owasp.properties
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/config/owasp.properties?rev=1713634&view=auto
==============================================================================
--- ofbiz/trunk/framework/base/config/owasp.properties (added)
+++ ofbiz/trunk/framework/base/config/owasp.properties Tue Nov 10 13:40:22 2015
@@ -0,0 +1,28 @@
+###############################################################################
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+###############################################################################
+
+####
+# OFBiz OWASP properties File https://www.owasp.org/index.php/Main_Page
+####
+
+# Should we use a permissive sanitizer policy? False By default!
+# This has a slightly impact on the code rendered, see last comments in OFBIZ-6669. 
+# Given as an example based on rendering cmssite, as it was before using the sanitizer.
+# You might even want to adapt the PERMISSIVE_POLICY to your needs... Be sure to check https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet before...
+sanitizer.permissive.policy=false

Propchange: ofbiz/trunk/framework/base/config/owasp.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/framework/base/config/owasp.properties
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/trunk/framework/base/config/owasp.properties
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/UtilCodec.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/UtilCodec.java?rev=1713634&r1=1713633&r2=1713634&view=diff
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/UtilCodec.java (original)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/UtilCodec.java Tue Nov 10 13:40:22 2015
@@ -18,11 +18,6 @@
  *******************************************************************************/
 package org.ofbiz.base.util;
 
-import org.owasp.esapi.codecs.Codec;
-import org.owasp.esapi.codecs.HTMLEntityCodec;
-import org.owasp.esapi.codecs.PercentCodec;
-import org.owasp.esapi.codecs.XMLEntityCodec;
-
 import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
 import java.net.URLEncoder;
@@ -34,6 +29,14 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.owasp.esapi.codecs.Codec;
+import org.owasp.esapi.codecs.HTMLEntityCodec;
+import org.owasp.esapi.codecs.PercentCodec;
+import org.owasp.esapi.codecs.XMLEntityCodec;
+import org.owasp.html.HtmlPolicyBuilder;
+import org.owasp.html.PolicyFactory;
+import org.owasp.html.Sanitizers;
+
 public class UtilCodec {
     private static final String module = UtilCodec.class.getName();
     private static final HtmlEncoder htmlEncoder = new HtmlEncoder();
@@ -48,6 +51,7 @@ public class UtilCodec {
         codecs = Collections.unmodifiableList(tmpCodecs);
     }
 
+    @SuppressWarnings("serial")
     public static class IntrusionException extends GeneralRuntimeException {
         public IntrusionException(String message) {
             super(message);
@@ -56,6 +60,7 @@ public class UtilCodec {
 
     public static interface SimpleEncoder {
         public String encode(String original);
+        public String sanitize(String outString); // Only really useful with HTML, else simply calls encode() method 
     }
 
     public static interface SimpleDecoder {
@@ -67,10 +72,30 @@ public class UtilCodec {
         private HTMLEntityCodec htmlCodec = new HTMLEntityCodec();
         public String encode(String original) {
             if (original == null) {
-       	    	return null;
-       	    }
-       	    return htmlCodec.encode(IMMUNE_HTML, original);
+                return null;
+            }
+            return htmlCodec.encode(IMMUNE_HTML, original);
+        }
+        public String sanitize(String original) {
+            if (original == null) {
+                return null;
+            }
+            PolicyFactory sanitizer = Sanitizers.FORMATTING.and(Sanitizers.BLOCKS).and(Sanitizers.IMAGES).and(Sanitizers.LINKS).and(Sanitizers.STYLES);
+            if (UtilProperties.getPropertyAsBoolean("owasp", "sanitizer.permissive.policy", false)) {
+                sanitizer = sanitizer.and(PERMISSIVE_POLICY);
+            }
+            return sanitizer.sanitize(original);
         }
+        // Given as an example based on rendering cmssite as it was before using the sanitizer.
+        // To use the PERMISSIVE_POLICY set sanitizer.permissive.policy to true. 
+        // Note that I was unable to render </html> and </body>. I guess because are <html> and <body> are not sanitized in 1st place (else the sanitizer makes some damages I found)
+        // You might even want to adapt the PERMISSIVE_POLICY to your needs... Be sure to check https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet before...
+        public static final PolicyFactory PERMISSIVE_POLICY = new HtmlPolicyBuilder()
+                .allowAttributes("id", "class").globally()
+                .allowElements("html", "body", "div", "center", "span", "table", "td")
+                .allowWithoutAttributes("html", "body", "div", "span", "table", "td")
+                .allowAttributes("width").onElements("table")
+                .toFactory();
     }
 
     public static class XmlEncoder implements SimpleEncoder {
@@ -78,9 +103,12 @@ public class UtilCodec {
         private XMLEntityCodec xmlCodec = new XMLEntityCodec();
         public String encode(String original) {
             if (original == null) {
-       	    	return null;
-       	    }
-       	    return xmlCodec.encode(IMMUNE_XML, original);
+                   return null;
+               }
+               return xmlCodec.encode(IMMUNE_XML, original);
+        }
+        public String sanitize(String original) {
+            return encode(original);
         }
     }
 
@@ -93,6 +121,9 @@ public class UtilCodec {
                 return null;
             }
         }
+        public String sanitize(String original) {
+            return encode(original);
+        }
 
         public String decode(String original) {
             try {
@@ -112,6 +143,9 @@ public class UtilCodec {
             }
             return original;
         }
+        public String sanitize(String original) {
+            return encode(original);
+        }
     }
 
     // ================== Begin General Functions ==================

Modified: ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/minilastviewedcategories.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/minilastviewedcategories.ftl?rev=1713634&r1=1713633&r2=1713634&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/minilastviewedcategories.ftl (original)
+++ ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/minilastviewedcategories.ftl Tue Nov 10 13:40:22 2015
@@ -40,7 +40,7 @@ under the License.
               <#elseif catContentWrappers?? && catContentWrappers[category.productCategoryId]?? && catContentWrappers[category.productCategoryId].get("DESCRIPTION", "html")??>
                 <a href="<@ofbizCatalogAltUrl productCategoryId=categoryId/>" class="browsecategorybutton">${catContentWrappers[category.productCategoryId].get("DESCRIPTION", "html")}</a>
               <#else>
-                <a href="<@ofbizCatalogAltUrl productCategoryId=categoryId/>" class="browsecategorybutton">${category.description!}</a>
+                <a href="<@ofbizCatalogAltUrl productCategoryId=categoryId/>" class="browsecategorybutton">${catContentWrappers[category.productCategoryId].get("DESCRIPTION", "html")}</a>
               </#if>
             </li>
           </#if>