You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by mr...@apache.org on 2026/08/18 13:10:40 UTC

(ofbiz-framework) branch release24.09 updated: Improved: Add permission check and path validation to imageCrop and imageRotate services

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 <mr...@gmail.com>
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;