From 7af57d810ffecc0c8c005c2a38bd08bbd6a5a0d4 Mon Sep 17 00:00:00 2001 From: Harness SAST and SCA Date: Wed, 20 May 2026 15:11:38 -0400 Subject: [PATCH 1/4] Fixing src/main/java/io/shiftleft/model/Customer.java for finding 3 --- .../java/io/shiftleft/model/Customer.java | 64 ++++++++++++++----- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/src/main/java/io/shiftleft/model/Customer.java b/src/main/java/io/shiftleft/model/Customer.java index 6ecdc30..b6f39bb 100644 --- a/src/main/java/io/shiftleft/model/Customer.java +++ b/src/main/java/io/shiftleft/model/Customer.java @@ -16,21 +16,33 @@ public class Customer { public Customer() { } - public Customer(String customerId, int clientId, String firstName, String lastName, Date dateOfBirth, String ssn, +public Customer(String customerId, int clientId, String firstName, String lastName, Date dateOfBirth, String ssn, String socialInsurancenum, String tin, String phoneNumber, Address address, Set accounts) { super(); + + // Sanitize all string inputs to prevent XSS and injection attacks this.clientId = clientId; - this.customerId = customerId; - this.firstName = firstName; - this.lastName = lastName; + this.customerId = sanitizeInput(customerId); + this.firstName = sanitizeInput(firstName); + this.lastName = sanitizeInput(lastName); this.dateOfBirth = dateOfBirth; - this.ssn = ssn; - this.socialInsurancenum = socialInsurancenum; - this.tin = tin; - this.phoneNumber = phoneNumber; + this.ssn = sanitizeInput(ssn); + this.socialInsurancenum = sanitizeInput(socialInsurancenum); + this.tin = sanitizeInput(tin); + this.phoneNumber = sanitizeInput(phoneNumber); this.address = address; this.accounts = accounts; - } +} + +// Helper method to sanitize inputs +private String sanitizeInput(String input) { + if (input == null) { + return null; + } + // Remove any HTML/script tags and escape special characters + return StringEscapeUtils.escapeHtml4(input.trim()); +} + @Id @GeneratedValue(strategy = GenerationType.AUTO) @@ -156,12 +168,32 @@ public void setAccounts(Set accounts) { this.accounts = accounts; } - @Override - public String toString() { - return "Customer [id=" + id + ", customerId=" + customerId + ", clientId=" + clientId + ", firstName=" + firstName - + ", lastName=" + lastName + ", dateOfBirth=" + dateOfBirth + ", ssn=" + ssn + ", socialInsurancenum=" - + socialInsurancenum + ", tin=" + tin + ", phoneNumber=" + phoneNumber + ", address=" + address + ", accounts=" - + accounts + "]"; - } +@Override +public String toString() { + // This method should not be used for HTML output to prevent XSS + // All fields are HTML-escaped for safety + return "Customer [id=" + StringEscapeUtils.escapeHtml4(String.valueOf(id)) + + ", customerId=" + StringEscapeUtils.escapeHtml4(customerId) + + ", clientId=" + clientId + + ", firstName=" + StringEscapeUtils.escapeHtml4(firstName) + + ", lastName=" + StringEscapeUtils.escapeHtml4(lastName) + + ", dateOfBirth=" + (dateOfBirth != null ? StringEscapeUtils.escapeHtml4(dateOfBirth.toString()) : "null") + + ", ssn=" + maskSensitiveData(ssn) + + ", socialInsurancenum=" + maskSensitiveData(socialInsurancenum) + + ", tin=" + maskSensitiveData(tin) + + ", phoneNumber=" + StringEscapeUtils.escapeHtml4(phoneNumber) + + ", address=" + (address != null ? StringEscapeUtils.escapeHtml4(address.toString()) : "null") + + ", accounts=" + (accounts != null ? StringEscapeUtils.escapeHtml4(accounts.toString()) : "null") + "]"; +} + +// Helper method to mask sensitive data in logs and output +private String maskSensitiveData(String data) { + if (data == null || data.length() < 4) { + return "****"; + } + // Show only last 4 characters for sensitive data + return "****" + StringEscapeUtils.escapeHtml4(data.substring(data.length() - 4)); +} + } From 8262e2ddf6cc571d5c8dd8de1c0200e350234967 Mon Sep 17 00:00:00 2001 From: Harness SAST and SCA Date: Wed, 20 May 2026 15:11:39 -0400 Subject: [PATCH 2/4] Fixing src/main/java/io/shiftleft/controller/CustomerController.java for finding 3 --- .../controller/CustomerController.java | 85 +++++++++++++------ 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/src/main/java/io/shiftleft/controller/CustomerController.java b/src/main/java/io/shiftleft/controller/CustomerController.java index 40e1c49..9a0805b 100644 --- a/src/main/java/io/shiftleft/controller/CustomerController.java +++ b/src/main/java/io/shiftleft/controller/CustomerController.java @@ -277,34 +277,65 @@ public void saveSettings(HttpServletResponse httpResponse, WebRequest request) t * @return String * @throws IOException */ - @RequestMapping(value = "/debug", method = RequestMethod.GET) - public String debug(@RequestParam String customerId, - @RequestParam int clientId, - @RequestParam String firstName, - @RequestParam String lastName, - @RequestParam String dateOfBirth, - @RequestParam String ssn, - @RequestParam String socialSecurityNum, - @RequestParam String tin, - @RequestParam String phoneNumber, - HttpServletResponse httpResponse, - WebRequest request) throws IOException{ - - // empty for now, because we debug +@RequestMapping(value = "/debug", method = RequestMethod.GET) +@ResponseBody +public String debug(@RequestParam @NotBlank @Size(max=50) @Pattern(regexp="^[a-zA-Z0-9-]+$") String customerId, + @RequestParam int clientId, + @RequestParam @NotBlank @Size(max=100) @Pattern(regexp="^[a-zA-Z\\s]+$") String firstName, + @RequestParam @NotBlank @Size(max=100) @Pattern(regexp="^[a-zA-Z\\s]+$") String lastName, + @RequestParam @NotBlank @Pattern(regexp="^\\d{4}-\\d{2}-\\d{2}$") String dateOfBirth, + @RequestParam @NotBlank @Pattern(regexp="^\\d{3}-\\d{2}-\\d{4}$") String ssn, + @RequestParam @NotBlank @Pattern(regexp="^\\d{3}-\\d{2}-\\d{4}$") String socialSecurityNum, + @RequestParam @NotBlank @Size(max=20) String tin, + @RequestParam @NotBlank @Pattern(regexp="^[0-9\\-\\+\\(\\)\\s]+$") String phoneNumber, + HttpServletResponse httpResponse, + WebRequest request) throws IOException { + + // Log the debug request for audit purposes + Logger logger = LoggerFactory.getLogger(CustomerController.class); + logger.info("Debug endpoint accessed for customerId: {}", StringEscapeUtils.escapeJava(customerId)); + + // Create customer object with validated inputs Set accounts1 = new HashSet(); - //dateofbirth example -> "1982-01-10" - Customer customer1 = new Customer(customerId, clientId, firstName, lastName, DateTime.parse(dateOfBirth).toDate(), - ssn, socialSecurityNum, tin, phoneNumber, new Address("Debug str", - "", "Debug city", "CA", "12345"), - accounts1); - - customerRepository.save(customer1); - httpResponse.setStatus(HttpStatus.CREATED.value()); - httpResponse.setHeader("Location", String.format("%s/customers/%s", - request.getContextPath(), customer1.getId())); - - return customer1.toString().toLowerCase().replace("script",""); - } + + try { + // Parse dateOfBirth with validation + Customer customer1 = new Customer(customerId, clientId, firstName, lastName, + DateTime.parse(dateOfBirth).toDate(), + ssn, socialSecurityNum, tin, phoneNumber, + new Address("Debug str", "", "Debug city", "CA", "12345"), + accounts1); + + // Save customer to repository + customerRepository.save(customer1); + + // Set response status and location header + httpResponse.setStatus(HttpStatus.CREATED.value()); + httpResponse.setHeader("Location", String.format("%s/customers/%s", + request.getContextPath(), customer1.getId())); + + // Return sanitized JSON response instead of toString() to avoid XSS + // Set content type to application/json to prevent HTML interpretation + httpResponse.setContentType("application/json"); + + // Create a safe JSON response with escaped values + String safeResponse = String.format( + "{\"status\":\"created\",\"customerId\":\"%s\",\"clientId\":%d,\"message\":\"Customer created successfully\"}", + StringEscapeUtils.escapeJson(customerId), + clientId + ); + + return safeResponse; + + } catch (IllegalArgumentException e) { + // Handle date parsing errors + logger.error("Invalid date format provided: {}", dateOfBirth); + httpResponse.setStatus(HttpStatus.BAD_REQUEST.value()); + httpResponse.setContentType("application/json"); + return "{\"error\":\"Invalid date format. Expected format: YYYY-MM-DD\"}"; + } +} + /** * Debug test for saving and reading a customer From 6c044ea38e68a42de4eea1462a13f21aae18dd38 Mon Sep 17 00:00:00 2001 From: Harness SAST and SCA Date: Wed, 20 May 2026 15:11:44 -0400 Subject: [PATCH 3/4] Fixing src/main/java/io/shiftleft/controller/CustomerController.java for finding 7 --- .../controller/CustomerController.java | 96 ++++++++++++++----- 1 file changed, 72 insertions(+), 24 deletions(-) diff --git a/src/main/java/io/shiftleft/controller/CustomerController.java b/src/main/java/io/shiftleft/controller/CustomerController.java index 9a0805b..51e1812 100644 --- a/src/main/java/io/shiftleft/controller/CustomerController.java +++ b/src/main/java/io/shiftleft/controller/CustomerController.java @@ -277,34 +277,82 @@ public void saveSettings(HttpServletResponse httpResponse, WebRequest request) t * @return String * @throws IOException */ -@RequestMapping(value = "/debug", method = RequestMethod.GET) -@ResponseBody -public String debug(@RequestParam @NotBlank @Size(max=50) @Pattern(regexp="^[a-zA-Z0-9-]+$") String customerId, +@RequestMapping(value = "/debug", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) +public String debug(@RequestParam String customerId, @RequestParam int clientId, - @RequestParam @NotBlank @Size(max=100) @Pattern(regexp="^[a-zA-Z\\s]+$") String firstName, - @RequestParam @NotBlank @Size(max=100) @Pattern(regexp="^[a-zA-Z\\s]+$") String lastName, - @RequestParam @NotBlank @Pattern(regexp="^\\d{4}-\\d{2}-\\d{2}$") String dateOfBirth, - @RequestParam @NotBlank @Pattern(regexp="^\\d{3}-\\d{2}-\\d{4}$") String ssn, - @RequestParam @NotBlank @Pattern(regexp="^\\d{3}-\\d{2}-\\d{4}$") String socialSecurityNum, - @RequestParam @NotBlank @Size(max=20) String tin, - @RequestParam @NotBlank @Pattern(regexp="^[0-9\\-\\+\\(\\)\\s]+$") String phoneNumber, + @RequestParam String firstName, + @RequestParam String lastName, + @RequestParam String dateOfBirth, + @RequestParam String ssn, + @RequestParam String socialSecurityNum, + @RequestParam String tin, + @RequestParam String phoneNumber, HttpServletResponse httpResponse, WebRequest request) throws IOException { - - // Log the debug request for audit purposes - Logger logger = LoggerFactory.getLogger(CustomerController.class); - logger.info("Debug endpoint accessed for customerId: {}", StringEscapeUtils.escapeJava(customerId)); - - // Create customer object with validated inputs - Set accounts1 = new HashSet(); - + + // Input validation for customerId + if (customerId == null || customerId.trim().isEmpty()) { + httpResponse.setStatus(HttpStatus.BAD_REQUEST.value()); + return "Invalid customerId"; + } + + // Input validation for names + if (firstName == null || firstName.trim().isEmpty() || + lastName == null || lastName.trim().isEmpty()) { + httpResponse.setStatus(HttpStatus.BAD_REQUEST.value()); + return "Invalid name parameters"; + } + + // Validate date format before parsing + if (dateOfBirth == null || !dateOfBirth.matches("\\d{4}-\\d{2}-\\d{2}")) { + httpResponse.setStatus(HttpStatus.BAD_REQUEST.value()); + return "Invalid date format. Expected: YYYY-MM-DD"; + } + try { - // Parse dateOfBirth with validation - Customer customer1 = new Customer(customerId, clientId, firstName, lastName, - DateTime.parse(dateOfBirth).toDate(), - ssn, socialSecurityNum, tin, phoneNumber, - new Address("Debug str", "", "Debug city", "CA", "12345"), - accounts1); + // Empty account set for debug purposes + Set accounts1 = new HashSet(); + + // Parse date with error handling + Customer customer1 = new Customer( + customerId, + clientId, + firstName, + lastName, + DateTime.parse(dateOfBirth).toDate(), + ssn, + socialSecurityNum, + tin, + phoneNumber, + new Address("Debug str", "", "Debug city", "CA", "12345"), + accounts1 + ); + + customerRepository.save(customer1); + httpResponse.setStatus(HttpStatus.CREATED.value()); + httpResponse.setHeader("Location", String.format("%s/customers/%s", + request.getContextPath(), customer1.getId())); + + // Sanitize output by HTML-encoding all user-controlled data + // This prevents XSS by converting special HTML characters to entities + String sanitizedOutput = StringEscapeUtils.escapeHtml4(customer1.toString()); + + // Set content type to plain text to prevent browser interpretation as HTML + httpResponse.setContentType(MediaType.TEXT_PLAIN_VALUE); + + return sanitizedOutput; + + } catch (IllegalArgumentException e) { + // Handle date parsing errors + httpResponse.setStatus(HttpStatus.BAD_REQUEST.value()); + return "Invalid date format"; + } catch (Exception e) { + // Handle other errors securely without exposing sensitive information + httpResponse.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); + return "An error occurred while processing the request"; + } +} + // Save customer to repository customerRepository.save(customer1); From 8b18355d1b831a8013afe27d69f7fc6f14cde3e3 Mon Sep 17 00:00:00 2001 From: Harness SAST and SCA Date: Wed, 20 May 2026 15:11:45 -0400 Subject: [PATCH 4/4] Fixing src/main/java/io/shiftleft/model/Customer.java for finding 7 --- .../java/io/shiftleft/model/Customer.java | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/main/java/io/shiftleft/model/Customer.java b/src/main/java/io/shiftleft/model/Customer.java index b6f39bb..0dd9eb8 100644 --- a/src/main/java/io/shiftleft/model/Customer.java +++ b/src/main/java/io/shiftleft/model/Customer.java @@ -19,21 +19,22 @@ public Customer() { public Customer(String customerId, int clientId, String firstName, String lastName, Date dateOfBirth, String ssn, String socialInsurancenum, String tin, String phoneNumber, Address address, Set accounts) { super(); - - // Sanitize all string inputs to prevent XSS and injection attacks + // Store data as-is in the model + // Sanitization should occur at the presentation layer when displaying to users this.clientId = clientId; - this.customerId = sanitizeInput(customerId); - this.firstName = sanitizeInput(firstName); - this.lastName = sanitizeInput(lastName); + this.customerId = customerId; + this.firstName = firstName; + this.lastName = lastName; this.dateOfBirth = dateOfBirth; - this.ssn = sanitizeInput(ssn); - this.socialInsurancenum = sanitizeInput(socialInsurancenum); - this.tin = sanitizeInput(tin); - this.phoneNumber = sanitizeInput(phoneNumber); + this.ssn = ssn; + this.socialInsurancenum = socialInsurancenum; + this.tin = tin; + this.phoneNumber = phoneNumber; this.address = address; this.accounts = accounts; } + // Helper method to sanitize inputs private String sanitizeInput(String input) { if (input == null) { @@ -170,22 +171,16 @@ public void setAccounts(Set accounts) { @Override public String toString() { - // This method should not be used for HTML output to prevent XSS - // All fields are HTML-escaped for safety - return "Customer [id=" + StringEscapeUtils.escapeHtml4(String.valueOf(id)) + - ", customerId=" + StringEscapeUtils.escapeHtml4(customerId) + - ", clientId=" + clientId + - ", firstName=" + StringEscapeUtils.escapeHtml4(firstName) + - ", lastName=" + StringEscapeUtils.escapeHtml4(lastName) + - ", dateOfBirth=" + (dateOfBirth != null ? StringEscapeUtils.escapeHtml4(dateOfBirth.toString()) : "null") + - ", ssn=" + maskSensitiveData(ssn) + - ", socialInsurancenum=" + maskSensitiveData(socialInsurancenum) + - ", tin=" + maskSensitiveData(tin) + - ", phoneNumber=" + StringEscapeUtils.escapeHtml4(phoneNumber) + - ", address=" + (address != null ? StringEscapeUtils.escapeHtml4(address.toString()) : "null") + - ", accounts=" + (accounts != null ? StringEscapeUtils.escapeHtml4(accounts.toString()) : "null") + "]"; + // Note: This toString method is used for debugging purposes + // When returning this to a web response, it MUST be HTML-encoded + // The encoding is handled at the controller layer (CustomerController.debug) + return "Customer [id=" + id + ", customerId=" + customerId + ", clientId=" + clientId + ", firstName=" + firstName + + ", lastName=" + lastName + ", dateOfBirth=" + dateOfBirth + ", ssn=" + ssn + ", socialInsurancenum=" + + socialInsurancenum + ", tin=" + tin + ", phoneNumber=" + phoneNumber + ", address=" + address + ", accounts=" + + accounts + "]"; } + // Helper method to mask sensitive data in logs and output private String maskSensitiveData(String data) { if (data == null || data.length() < 4) {