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;