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

ashishvijaywargiya pushed a commit to branch release24.09
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/release24.09 by this push:
     new a3b1039944 Fixed: arbitrary service execution via Content.serviceName 
in ContentWorker (#1791)
a3b1039944 is described below

commit a3b10399441d0d17c65c12a63c24d2ecf83ab306
Author: Ashish Vijaywargiya <[email protected]>
AuthorDate: Thu Aug 27 18:52:59 2026 +0530

    Fixed: arbitrary service execution via Content.serviceName in ContentWorker 
(#1791)
    
    renderContentAsText resolved and ran whatever service name was stored in
    Content.serviceName, a plain non-primary-key field writable by any
    CONTENTMGR_CREATE/UPDATE account through createContent/updateContent,
    using the live HTTP request parameters as the service's input. Some
    content-rendering routes require no authentication, so an armed row
    could be triggered anonymously.
    
    - ContentWorker no longer reads Content.serviceName; the customMethodId
    path now requires the referenced CustomMethod be typed CONTENT_RENDER
    - Locked serviceName and customMethodId out of mass assignment on
    createContent, updateContent, createProductContent and
    updateProductContent
    - Removed the now-dead serviceName field from the Catalog Manager
    external content form
    - Added CONTENT_RENDER as a seed CustomMethodType
    
    Thank you Krishna Uprit for your help.
    
    Cherry-picked from 555f76f7e3679d03f4813ba90edebf57a5fd27a3 (trunk,
    #1788), excluding the accompanying ContentTests.groovy test changes.
---
 applications/content/servicedef/services_content.xml     |  8 ++++++++
 .../org/apache/ofbiz/content/content/ContentWorker.java  | 16 ++++++++++++++--
 applications/product/servicedef/services.xml             |  8 ++++++++
 applications/product/widget/catalog/ProductForms.xml     |  1 -
 framework/common/data/CommonTypeData.xml                 |  3 +++
 5 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/applications/content/servicedef/services_content.xml 
b/applications/content/servicedef/services_content.xml
index 4adcb78963..5857a4476d 100644
--- a/applications/content/servicedef/services_content.xml
+++ b/applications/content/servicedef/services_content.xml
@@ -47,6 +47,10 @@
         <override name="statusId" default-value="CTNT_IN_PROGRESS"/>
         <override name="contentName" allow-html="safe"/>
         <override name="description" allow-html="safe"/>
+        <!-- serviceName/customMethodId choose what code renderContentAsText 
runs against the live request
+             parameters; neither is set through this generic mass-assignment 
path (see ContentWorker.java) -->
+        <override name="serviceName" mode="OUT"/>
+        <override name="customMethodId" mode="OUT"/>
     </service>
 
     <service name="createTextAndUploadedContent" engine="groovy" auth="true"
@@ -140,6 +144,10 @@
         <!-- end of deprecated fields -->
         <override name="contentName" allow-html="safe"/>
         <override name="description" allow-html="safe"/>
+        <!-- serviceName/customMethodId choose what code renderContentAsText 
runs against the live request
+             parameters; neither is set through this generic mass-assignment 
path (see ContentWorker.java) -->
+        <override name="serviceName" mode="OUT"/>
+        <override name="customMethodId" mode="OUT"/>
     </service>
 
     <service name="updateTextContent" engine="group" auth="true">
diff --git 
a/applications/content/src/main/java/org/apache/ofbiz/content/content/ContentWorker.java
 
b/applications/content/src/main/java/org/apache/ofbiz/content/content/ContentWorker.java
index f7895cb53a..914f51ba61 100644
--- 
a/applications/content/src/main/java/org/apache/ofbiz/content/content/ContentWorker.java
+++ 
b/applications/content/src/main/java/org/apache/ofbiz/content/content/ContentWorker.java
@@ -197,10 +197,22 @@ public class ContentWorker implements 
org.apache.ofbiz.widget.content.ContentWor
         // if the content has a service attached run the service
 
         Delegator delegator = dispatcher.getDelegator();
-        String serviceName = content.getString("serviceName"); //Kept for 
backward compatibility
+        // NOTE: Content.serviceName is a legacy, client-writable field 
(createContent/updateContent both
+        // accept it as a plain non-PK attribute) that used to be resolved and 
run here directly; that let
+        // anyone able to write a Content row choose an arbitrary service to 
run with the live HTTP request
+        // parameters as its input. It is no longer honored. Only a 
CustomMethod explicitly typed for
+        // content rendering may be run, so arming a row requires a 
CustomMethod that was deliberately set
+        // up for this purpose, not just a string dropped into the Content row 
itself.
+        String serviceName = null;
         GenericValue custMethod = null;
         if (UtilValidate.isNotEmpty(content.getString("customMethodId"))) {
-            custMethod = 
EntityQuery.use(delegator).from("CustomMethod").where("customMethodId", 
content.get("customMethodId")).cache().queryOne();
+            custMethod = EntityQuery.use(delegator).from("CustomMethod")
+                    .where("customMethodId", content.get("customMethodId"), 
"customMethodTypeId", "CONTENT_RENDER")
+                    .cache().queryOne();
+            if (custMethod == null) {
+                throw new GeneralException("customMethodId [" + 
content.get("customMethodId")
+                        + "] on content [" + content.get("contentId") + "] is 
not a content rendering method");
+            }
         }
         if (custMethod != null) serviceName = 
custMethod.getString("customMethodName");
         if (UtilValidate.isNotEmpty(serviceName)) {
diff --git a/applications/product/servicedef/services.xml 
b/applications/product/servicedef/services.xml
index ae6b975b52..fddd781c8e 100644
--- a/applications/product/servicedef/services.xml
+++ b/applications/product/servicedef/services.xml
@@ -366,6 +366,10 @@ under the License.
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
         <auto-attributes entity-name="Content" include="nonpk" mode="IN" 
optional="true"/>
         <override name="fromDate" default-value="${date:nowTimestamp()}"/>
+        <!-- serviceName/customMethodId choose what code renderContentAsText 
runs against the live request
+             parameters; neither is set through this generic mass-assignment 
path (see ContentWorker.java) -->
+        <override name="serviceName" mode="OUT"/>
+        <override name="customMethodId" mode="OUT"/>
     </service>
     <service name="updateProductContent" default-entity-name="ProductContent" 
engine="groovy"
         
location="component://product/src/main/groovy/org/apache/ofbiz/product/product/product/ProductContentServicesScript.groovy"
 invoke="updateProductContent" auth="true">
@@ -373,6 +377,10 @@ under the License.
         <auto-attributes include="pk" mode="IN" optional="false"/>
         <auto-attributes include="nonpk" mode="IN" optional="true"/>
         <auto-attributes entity-name="Content" include="nonpk" mode="IN" 
optional="true"/>
+        <!-- serviceName/customMethodId choose what code renderContentAsText 
runs against the live request
+             parameters; neither is set through this generic mass-assignment 
path (see ContentWorker.java) -->
+        <override name="serviceName" mode="OUT"/>
+        <override name="customMethodId" mode="OUT"/>
     </service>
     <service name="removeProductContent" default-entity-name="ProductContent" 
engine="entity-auto" invoke="delete" auth="true">
         <description>Remove Content From Product</description>
diff --git a/applications/product/widget/catalog/ProductForms.xml 
b/applications/product/widget/catalog/ProductForms.xml
index da80f0208b..839d95f0e8 100644
--- a/applications/product/widget/catalog/ProductForms.xml
+++ b/applications/product/widget/catalog/ProductForms.xml
@@ -775,7 +775,6 @@ under the License.
         <field name="description" 
title="${uiLabelMap.ProductProductDescription}" map-name="content"><text 
size="40"/></field>
         <field name="fromDate" title="${uiLabelMap.CommonFromDate}" ></field>
         <field name="thruDate" title="${uiLabelMap.CommonThruDate}"></field>
-        <field name="serviceName" title="${uiLabelMap.ProductServiceName}" 
map-name="content"><text size="40"/></field>
         <field use-when="contentId == null" name="contentId" 
title="${uiLabelMap.ProductContentId}" 
tooltip="${uiLabelMap.ProductOptional}"><text maxlength="20"/></field>
         <field use-when="contentId != null" name="contentId" 
title="${uiLabelMap.ProductContentId}" 
tooltip="${uiLabelMap.ProductNotModificationRecrationProductContentAssociation}"
 map-name="productContentData" ><display/></field>
         <field name="productId"><hidden/></field>
diff --git a/framework/common/data/CommonTypeData.xml 
b/framework/common/data/CommonTypeData.xml
index 70c32c91b3..53c675eed6 100644
--- a/framework/common/data/CommonTypeData.xml
+++ b/framework/common/data/CommonTypeData.xml
@@ -152,4 +152,7 @@ under the License.
     <TelecomMethodType telecomMethodTypeId="SMS" description="Short Messaging 
Service Method"/>
     <TelecomMethodType telecomMethodTypeId="WHATSAPP" description="WhatsApp 
Messaging Service Method"/>
     <CustomMethodType customMethodTypeId="TELECOM_GATEWAY" 
description="Telecom Gateway Custom Method"/>
+
+    <!-- Content Rendering Custom Method -->
+    <CustomMethodType customMethodTypeId="CONTENT_RENDER" description="Content 
Rendering Method"/>
 </entity-engine-xml>

Reply via email to