From b4c9940013e80446173e8d4f5be01b75d70aed93 Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Mon, 20 Apr 2026 10:45:45 -0600 Subject: [PATCH] add XSS content filter to DTOs --- .../backend/dto/category/CategoryRequest.java | 2 ++ .../petshop/backend/dto/pet/PetRequest.java | 2 ++ .../backend/dto/product/ProductRequest.java | 3 +++ .../backend/dto/service/ServiceRequest.java | 3 +++ .../backend/dto/store/StoreRequest.java | 2 ++ .../backend/dto/supplier/SupplierRequest.java | 1 + .../petshop/backend/dto/user/UserRequest.java | 3 +++ .../com/petshop/backend/util/SafeContent.java | 17 +++++++++++++++++ .../backend/util/SafeContentValidator.java | 18 ++++++++++++++++++ 9 files changed, 51 insertions(+) create mode 100644 backend/src/main/java/com/petshop/backend/util/SafeContent.java create mode 100644 backend/src/main/java/com/petshop/backend/util/SafeContentValidator.java diff --git a/backend/src/main/java/com/petshop/backend/dto/category/CategoryRequest.java b/backend/src/main/java/com/petshop/backend/dto/category/CategoryRequest.java index c012ae21..b099826f 100644 --- a/backend/src/main/java/com/petshop/backend/dto/category/CategoryRequest.java +++ b/backend/src/main/java/com/petshop/backend/dto/category/CategoryRequest.java @@ -1,10 +1,12 @@ package com.petshop.backend.dto.category; +import com.petshop.backend.util.SafeContent; import jakarta.validation.constraints.NotBlank; import java.util.Objects; public class CategoryRequest { @NotBlank(message = "Category name is required") + @SafeContent private String categoryName; private String categoryType; diff --git a/backend/src/main/java/com/petshop/backend/dto/pet/PetRequest.java b/backend/src/main/java/com/petshop/backend/dto/pet/PetRequest.java index c22a5da6..4d0986bb 100644 --- a/backend/src/main/java/com/petshop/backend/dto/pet/PetRequest.java +++ b/backend/src/main/java/com/petshop/backend/dto/pet/PetRequest.java @@ -1,5 +1,6 @@ package com.petshop.backend.dto.pet; +import com.petshop.backend.util.SafeContent; import jakarta.validation.constraints.DecimalMax; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -11,6 +12,7 @@ import java.util.Objects; public class PetRequest { @NotBlank(message = "Pet name is required") + @SafeContent private String petName; @NotBlank(message = "Species is required") diff --git a/backend/src/main/java/com/petshop/backend/dto/product/ProductRequest.java b/backend/src/main/java/com/petshop/backend/dto/product/ProductRequest.java index 71dd600f..e1ca9241 100644 --- a/backend/src/main/java/com/petshop/backend/dto/product/ProductRequest.java +++ b/backend/src/main/java/com/petshop/backend/dto/product/ProductRequest.java @@ -1,5 +1,6 @@ package com.petshop.backend.dto.product; +import com.petshop.backend.util.SafeContent; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; @@ -8,11 +9,13 @@ import java.util.Objects; public class ProductRequest { @NotBlank(message = "Product name is required") + @SafeContent private String prodName; @NotNull(message = "Category ID is required") private Long categoryId; + @SafeContent private String prodDesc; @NotNull(message = "Product price is required") diff --git a/backend/src/main/java/com/petshop/backend/dto/service/ServiceRequest.java b/backend/src/main/java/com/petshop/backend/dto/service/ServiceRequest.java index 977b72cc..464fefda 100644 --- a/backend/src/main/java/com/petshop/backend/dto/service/ServiceRequest.java +++ b/backend/src/main/java/com/petshop/backend/dto/service/ServiceRequest.java @@ -1,5 +1,6 @@ package com.petshop.backend.dto.service; +import com.petshop.backend.util.SafeContent; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; @@ -10,8 +11,10 @@ import java.util.Set; public class ServiceRequest { @NotBlank(message = "Service name is required") + @SafeContent private String serviceName; + @SafeContent private String serviceDesc; @NotNull(message = "Service price is required") diff --git a/backend/src/main/java/com/petshop/backend/dto/store/StoreRequest.java b/backend/src/main/java/com/petshop/backend/dto/store/StoreRequest.java index 5bb68613..fca03db1 100644 --- a/backend/src/main/java/com/petshop/backend/dto/store/StoreRequest.java +++ b/backend/src/main/java/com/petshop/backend/dto/store/StoreRequest.java @@ -1,11 +1,13 @@ package com.petshop.backend.dto.store; +import com.petshop.backend.util.SafeContent; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import java.util.Objects; public class StoreRequest { @NotBlank(message = "Store name is required") + @SafeContent private String storeName; @NotBlank(message = "Address is required") diff --git a/backend/src/main/java/com/petshop/backend/dto/supplier/SupplierRequest.java b/backend/src/main/java/com/petshop/backend/dto/supplier/SupplierRequest.java index b7ae7efb..a0eb2b6a 100644 --- a/backend/src/main/java/com/petshop/backend/dto/supplier/SupplierRequest.java +++ b/backend/src/main/java/com/petshop/backend/dto/supplier/SupplierRequest.java @@ -1,5 +1,6 @@ package com.petshop.backend.dto.supplier; +import com.petshop.backend.util.SafeContent; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import java.util.Objects; diff --git a/backend/src/main/java/com/petshop/backend/dto/user/UserRequest.java b/backend/src/main/java/com/petshop/backend/dto/user/UserRequest.java index 774e9d90..04c82e43 100644 --- a/backend/src/main/java/com/petshop/backend/dto/user/UserRequest.java +++ b/backend/src/main/java/com/petshop/backend/dto/user/UserRequest.java @@ -1,5 +1,6 @@ package com.petshop.backend.dto.user; +import com.petshop.backend.util.SafeContent; import com.petshop.backend.entity.User; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; @@ -15,10 +16,12 @@ public class UserRequest { private String password; @NotBlank(message = "First name is required") + @SafeContent @Size(max = 50) private String firstName; @NotBlank(message = "Last name is required") + @SafeContent @Size(max = 50) private String lastName; diff --git a/backend/src/main/java/com/petshop/backend/util/SafeContent.java b/backend/src/main/java/com/petshop/backend/util/SafeContent.java new file mode 100644 index 00000000..6db91b6e --- /dev/null +++ b/backend/src/main/java/com/petshop/backend/util/SafeContent.java @@ -0,0 +1,17 @@ +package com.petshop.backend.util; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = SafeContentValidator.class) +public @interface SafeContent { + String message() default "Content contains prohibited characters or scripts"; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/backend/src/main/java/com/petshop/backend/util/SafeContentValidator.java b/backend/src/main/java/com/petshop/backend/util/SafeContentValidator.java new file mode 100644 index 00000000..6d3af630 --- /dev/null +++ b/backend/src/main/java/com/petshop/backend/util/SafeContentValidator.java @@ -0,0 +1,18 @@ +package com.petshop.backend.util; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import java.util.regex.Pattern; + +public class SafeContentValidator implements ConstraintValidator { + + private static final Pattern DANGEROUS = Pattern.compile( + "]+on\\w+", + Pattern.CASE_INSENSITIVE); + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if (value == null || value.isBlank()) return true; + return !DANGEROUS.matcher(value).find(); + } +}