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 4bae54df46 Fixed: updateLayout authorizing under CONTENT_CREATE then 
updating unrelated records unchecked (#1745) (#1746)
4bae54df46 is described below

commit 4bae54df463e21ecdc9aeb52297386cccef0862e
Author: Ashish Vijaywargiya <[email protected]>
AuthorDate: Wed Aug 26 23:10:08 2026 +0530

    Fixed: updateLayout authorizing under CONTENT_CREATE then updating 
unrelated records unchecked (#1745) (#1746)
    
    The updateLayout event built a Content value from caller-supplied
    parameters and checked permission for it under the CONTENT_CREATE
    operation, then separately loaded the real Content identified by
    parameters.contentId and the real DataResource identified by
    parameters.dataResourceId and stored both directly, without checking
    UPDATE permission on either record and without any check that the
    DataResource actually belonged to the Content.
    
    A user holding only view-level Content Manager permissions could use an
    existing RESPONSE-purpose Content to pass the CONTENT_CREATE check, then
    relink that Content to an arbitrary DataResource and convert it into a
    template-bearing (FTL) OFBIZ_FILE resource - a path the normal
    updateDataResource service already blocks for the same user, since it
    requires CONTENTMGR_SUPER for template-bearing DataResources.
    
    Route both updates through the existing updateContent/updateDataResource
    services instead, so permission is checked (via
    genericContentPermission/ genericDataResourcePermission, main-action
    UPDATE) against the real target records, the same way every other update
    path in this component already works.
    
    Test coverage from the original commit is omitted here per request.
    
    Thank you Krishna Uprit for your help in reviewing the changes.
    
    (cherry picked from commit 4cc9848625cfe4d22765167b6476573752f74c82)
---
 .../content/minilang/layout/LayoutEvents.xml       | 43 ++++++++++------------
 1 file changed, 20 insertions(+), 23 deletions(-)

diff --git a/applications/content/minilang/layout/LayoutEvents.xml 
b/applications/content/minilang/layout/LayoutEvents.xml
index c063808bd5..07441c969d 100644
--- a/applications/content/minilang/layout/LayoutEvents.xml
+++ b/applications/content/minilang/layout/LayoutEvents.xml
@@ -52,37 +52,34 @@ under the License.
     <simple-method login-required="true" method-name="updateLayout" 
short-description="Update Layout">
         <log level="info" message="in updateLayout."/>
 
-        <make-value entity-name="Content" value-field="currentContent"/>
-        <set-pk-fields map="parameters" value-field="currentContent"/>
-        <set-nonpk-fields map="parameters" value-field="currentContent"/>
-        <set field="context.currentContent" from-field="currentContent"/>
+        <!-- Route the actual persistence through 
updateContent/updateDataResource so permission is
+             checked (via 
genericContentPermission/genericDataResourcePermission, main-action UPDATE)
+             against the real target Content and DataResource records 
identified by parameters.contentId
+             and parameters.dataResourceId, instead of against an 
attacker-constructed value under the
+             unrelated CONTENT_CREATE operation. This also ensures converting 
the target DataResource
+             into a template-bearing (e.g. FTL) resource is gated behind 
CONTENTMGR_SUPER, same as the
+             normal updateDataResource path. -->
+        <make-value entity-name="Content" value-field="content"/>
+        <set-pk-fields map="parameters" value-field="content"/>
+        <set-nonpk-fields map="parameters" value-field="content"/>
+        <log level="info" message="content: ${content}"/>
+        <map-to-map map="content" to-map="context"/>
         <set field="context.contentPurposeTypeId" 
from-field="parameters.contentPurposeTypeId"/>
-        <string-to-list list="targetOperationList" string="CONTENT_CREATE"/>
-        <set field="context.targetOperationList" 
from-field="targetOperationList"/>
         <session-to-field field="context.userLogin" session-name="userLogin"/>
-        <call-service in-map-name="context" 
service-name="checkContentPermission">
-            <result-to-field result-name="permissionStatus" 
field="permissionStatus"/>
-        </call-service>
-        <if-compare field="permissionStatus" operator="not-equals" 
value="granted" type="String">
-            <add-error>
-                <fail-property resource="ContentUiLabels" 
property="ContentPermissionNotGranted"/>
-            </add-error>
-        </if-compare>
+        <call-service in-map-name="context" service-name="updateContent"/>
         <check-errors/>
-        <set field="content.contentId" from-field="parameters.contentId"/>
-        <find-by-primary-key entity-name="Content" value-field="content" 
map="content"/>
-        <set-nonpk-fields map="parameters" value-field="content"/>
-        <log level="info" message="content: ${content}"/>
-        <store-value value-field="content"/>
         <field-to-request field="content.contentId" request-name="contentId"/>
-        <set field="dataResource.dataResourceId" 
from-field="parameters.dataResourceId"/>
-        <find-by-primary-key entity-name="DataResource" 
value-field="dataResource" map="dataResource"/>
+
+        <make-value entity-name="DataResource" value-field="dataResource"/>
+        <set-pk-fields map="parameters" value-field="dataResource"/>
         <set-nonpk-fields map="parameters" value-field="dataResource"/>
         <set field="dataResource.objectInfo" 
from-field="parameters.drObjectInfo"/>
         <log level="info" message="dataResource: ${dataResource}"/>
-        <store-value value-field="dataResource"/>
-        <field-to-request field="dataResource.dataResourceId" 
request-name="drDataResourceId"/>
+        <map-to-map map="dataResource" to-map="context2"/>
+        <session-to-field field="context2.userLogin" session-name="userLogin"/>
+        <call-service in-map-name="context2" 
service-name="updateDataResource"/>
         <check-errors/>
+        <field-to-request field="dataResource.dataResourceId" 
request-name="drDataResourceId"/>
     </simple-method>
 
     <simple-method login-required="true" method-name="createLayoutText" 
short-description="Create Layout Text">

Reply via email to