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

mridulpathak 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 80f4315d17 Improved: Add permission check and path validation to 
imageCrop and imageRotate services
80f4315d17 is described below

commit 80f4315d17176aae55091286de03d5049a30be32
Author: Mridul Pathak <[email protected]>
AuthorDate: Tue Aug 18 18:40:35 2026 +0530

    Improved: Add permission check and path validation to imageCrop and 
imageRotate services
    
    Backported from trunk (#1674).
---
 .../ofbiz/product/imagemanagement/CropImage.java   | 33 +++++++++++++++++---
 .../ofbiz/product/imagemanagement/RotateImage.java | 35 ++++++++++++++++++----
 2 files changed, 59 insertions(+), 9 deletions(-)

diff --git 
a/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/CropImage.java
 
b/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/CropImage.java
index 419b74d03d..6bc636f648 100644
--- 
a/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/CropImage.java
+++ 
b/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/CropImage.java
@@ -22,6 +22,8 @@ import java.awt.image.BufferedImage;
 import java.awt.image.RenderedImage;
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -30,12 +32,14 @@ import javax.imageio.ImageIO;
 
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.UtilDateTime;
+import org.apache.ofbiz.base.util.UtilMisc;
 import org.apache.ofbiz.base.util.UtilProperties;
 import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.base.util.string.FlexibleStringExpander;
 import org.apache.ofbiz.entity.Delegator;
 import org.apache.ofbiz.entity.GenericValue;
 import org.apache.ofbiz.entity.util.EntityUtilProperties;
+import org.apache.ofbiz.security.Security;
 import org.apache.ofbiz.service.DispatchContext;
 import org.apache.ofbiz.service.GenericServiceException;
 import org.apache.ofbiz.service.LocalDispatcher;
@@ -64,7 +68,32 @@ public class CropImage {
         String imageW = (String) context.get("imageW");
         String imageH = (String) context.get("imageH");
 
+        Security security = dctx.getSecurity();
+        if (!security.hasPermission("IMAGE_MANAGEMENT_ADMIN", userLogin)) {
+            String errMsg = UtilProperties.getMessage(RES_ERROR, 
"ProductImageManagementPermissionError", locale);
+            Debug.logError(errMsg, MODULE);
+            return ServiceUtil.returnError(errMsg);
+        }
+
+        String imageServerPath = 
FlexibleStringExpander.expandString(EntityUtilProperties.getPropertyValue("catalog",
+                "image.management.path", delegator), context);
+        String imageServerUrl = 
FlexibleStringExpander.expandString(EntityUtilProperties.getPropertyValue("catalog",
+                "image.management.url", delegator), context);
+
         if (UtilValidate.isNotEmpty(imageName)) {
+            Path imageServerNormalizedPath = 
Paths.get(imageServerPath).normalize();
+            Path resolvedProductDir = Paths.get(imageServerPath, 
productId).normalize();
+            if (!resolvedProductDir.startsWith(imageServerNormalizedPath)) {
+                Debug.logError("Path traversal attempt detected in image crop, 
productId: " + productId, MODULE);
+                return 
ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE,
+                        "ProductImageViewUnableWriteFile", 
UtilMisc.toMap("fileName", resolvedProductDir.toString()), locale));
+            }
+            if 
(!ImageManagementServices.isValidProductImageFileName(imageName, 
resolvedProductDir, delegator)) {
+                Debug.logError("Path traversal attempt detected in image crop, 
imageName: " + imageName, MODULE);
+                return 
ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE,
+                        "ProductImageViewUnableWriteFile", 
UtilMisc.toMap("fileName", imageName), locale));
+            }
+
             Map<String, Object> contentCtx = new HashMap<>();
             contentCtx.put("contentTypeId", "DOCUMENT");
             contentCtx.put("userLogin", userLogin);
@@ -98,10 +127,6 @@ public class CropImage {
             String filenameToUse = (String) contentResult.get("contentId") + 
".jpg";
             String filenameTouseThumb = (String) 
contentResult.get("contentId") + nameOfThumb + ".jpg";
 
-            String imageServerPath = 
FlexibleStringExpander.expandString(EntityUtilProperties.getPropertyValue("catalog",
-                    "image.management.path", delegator), context);
-            String imageServerUrl = 
FlexibleStringExpander.expandString(EntityUtilProperties.getPropertyValue("catalog",
-                    "image.management.url", delegator), context);
             BufferedImage bufImg = ImageIO.read(new File(imageServerPath + "/" 
+ productId + "/" + imageName));
 
             int x = Integer.parseInt(imageX);
diff --git 
a/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/RotateImage.java
 
b/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/RotateImage.java
index bc3cbb1355..6137acf264 100644
--- 
a/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/RotateImage.java
+++ 
b/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/RotateImage.java
@@ -23,6 +23,8 @@ import java.awt.image.BufferedImage;
 import java.awt.image.RenderedImage;
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -31,12 +33,14 @@ import javax.imageio.ImageIO;
 
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.UtilDateTime;
+import org.apache.ofbiz.base.util.UtilMisc;
 import org.apache.ofbiz.base.util.UtilProperties;
 import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.base.util.string.FlexibleStringExpander;
 import org.apache.ofbiz.entity.Delegator;
 import org.apache.ofbiz.entity.GenericValue;
 import org.apache.ofbiz.entity.util.EntityUtilProperties;
+import org.apache.ofbiz.security.Security;
 import org.apache.ofbiz.service.DispatchContext;
 import org.apache.ofbiz.service.GenericServiceException;
 import org.apache.ofbiz.service.LocalDispatcher;
@@ -47,7 +51,7 @@ public class RotateImage {
 
     private static final String MODULE = RotateImage.class.getName();
     private static final String RES_ERROR = "ProductErrorUiLabels";
-    private static final String RESOURCE = "ProductFUiLabels";
+    private static final String RESOURCE = "ProductUiLabels";
 
     public static Map<String, Object> imageRotate(DispatchContext dctx, 
Map<String, ? extends Object> context)
             throws IOException {
@@ -62,7 +66,32 @@ public class RotateImage {
         String imageName = (String) context.get("imageName");
         String angle = (String) context.get("angle");
 
+        Security security = dctx.getSecurity();
+        if (!security.hasPermission("IMAGE_MANAGEMENT_ADMIN", userLogin)) {
+            String errMsg = UtilProperties.getMessage(RES_ERROR, 
"ProductImageManagementPermissionError", locale);
+            Debug.logError(errMsg, MODULE);
+            return ServiceUtil.returnError(errMsg);
+        }
+
+        String imageServerPath = 
FlexibleStringExpander.expandString(EntityUtilProperties.getPropertyValue("catalog",
+                "image.management.path", delegator), context);
+        String imageServerUrl = 
FlexibleStringExpander.expandString(EntityUtilProperties.getPropertyValue("catalog",
+                "image.management.url", delegator), context);
+
         if (UtilValidate.isNotEmpty(imageName)) {
+            Path imageServerNormalizedPath = 
Paths.get(imageServerPath).normalize();
+            Path resolvedProductDir = Paths.get(imageServerPath, 
productId).normalize();
+            if (!resolvedProductDir.startsWith(imageServerNormalizedPath)) {
+                Debug.logError("Path traversal attempt detected in image 
rotate, productId: " + productId, MODULE);
+                return 
ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE,
+                        "ProductImageViewUnableWriteFile", 
UtilMisc.toMap("fileName", resolvedProductDir.toString()), locale));
+            }
+            if 
(!ImageManagementServices.isValidProductImageFileName(imageName, 
resolvedProductDir, delegator)) {
+                Debug.logError("Path traversal attempt detected in image 
rotate, imageName: " + imageName, MODULE);
+                return 
ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE,
+                        "ProductImageViewUnableWriteFile", 
UtilMisc.toMap("fileName", imageName), locale));
+            }
+
             Map<String, Object> contentCtx = new HashMap<>();
             contentCtx.put("contentTypeId", "DOCUMENT");
             contentCtx.put("userLogin", userLogin);
@@ -96,10 +125,6 @@ public class RotateImage {
             String filenameToUse = (String) contentResult.get("contentId") + 
".jpg";
             String filenameTouseThumb = (String) 
contentResult.get("contentId") + nameOfThumb + ".jpg";
 
-            String imageServerPath = 
FlexibleStringExpander.expandString(EntityUtilProperties.getPropertyValue("catalog",
-                    "image.management.path", delegator), context);
-            String imageServerUrl = 
FlexibleStringExpander.expandString(EntityUtilProperties.getPropertyValue("catalog",
-                    "image.management.url", delegator), context);
             BufferedImage bufImg = ImageIO.read(new File(imageServerPath + "/" 
+ productId + "/" + imageName));
 
             int bufImgType;

Reply via email to