From 74d6b8bbd98bbdcd4c4a7a13d10fb5729a7076be Mon Sep 17 00:00:00 2001 From: Harness SAST and SCA Date: Thu, 12 Feb 2026 00:23:32 -0500 Subject: [PATCH] Fixing src/main/java/io/shiftleft/controller/CustomerController.java for finding 12 --- .../controller/CustomerController.java | 97 +++++++++++++------ 1 file changed, 67 insertions(+), 30 deletions(-) diff --git a/src/main/java/io/shiftleft/controller/CustomerController.java b/src/main/java/io/shiftleft/controller/CustomerController.java index b13ba0d07..616c32efd 100644 --- a/src/main/java/io/shiftleft/controller/CustomerController.java +++ b/src/main/java/io/shiftleft/controller/CustomerController.java @@ -20,37 +20,74 @@ public void saveSettings(HttpServletResponse httpResponse, WebRequest request) t String base64txt = cookie[0].replace("settings=",""); // Check md5sum - String cookieMD5sum = cookie[1]; - String calcMD5Sum = DigestUtils.md5Hex(base64txt); -if(!cookieMD5sum.equals(calcMD5Sum)) - { - httpResponse.getOutputStream().println("Wrong md5"); - throw new Exception("Invalid MD5"); - } +@RequestMapping(value = "/saveSettings", method = RequestMethod.GET) + public void saveSettings(HttpServletResponse httpResponse, WebRequest request) throws Exception { + if (!checkCookie(request)) { + httpResponse.getOutputStream().println("Error"); + throw new Exception("cookie is incorrect"); + } - // Now we can store on filesystem - String[] settings = new String(Base64.getDecoder().decode(base64txt)).split(","); -// storage will have ClassPathResource as basepath - ClassPathResource cpr = new ClassPathResource("./static/"); + String settingsCookie = request.getHeader("Cookie"); + String[] cookie = settingsCookie.split(","); + if (cookie.length < 2) { + httpResponse.getOutputStream().println("Malformed cookie"); + throw new Exception("cookie is incorrect"); + } - // Whitelist the filename to prevent directory traversal - String filename = settings[0]; - if(!filename.matches("[a-zA-Z0-9._-]+")) { - httpResponse.getOutputStream().println("Invalid filename"); - throw new Exception("Filename contains invalid characters"); - } + String base64txt = cookie[0].replace("settings=", ""); + String cookieMD5sum = cookie[1]; + String calcMD5Sum = DigestUtils.md5Hex(base64txt); - File file = new File(cpr.getPath()+filename); - if(!file.exists()) { - file.getParentFile().mkdirs(); - } + if (!cookieMD5sum.equals(calcMD5Sum)) { + httpResponse.getOutputStream().println("Wrong md5"); + throw new Exception("Invalid MD5"); + } - FileOutputStream fos = new FileOutputStream(file, true); - // First entry is the filename -> remove it - String[] settingsArr = Arrays.copyOfRange(settings, 1, settings.length); - // on setting at a linez - fos.write(String.join("\n",settingsArr).getBytes()); - fos.write(("\n"+cookie[cookie.length-1]).getBytes()); - fos.close(); - httpResponse.getOutputStream().println("Settings Saved"); - } + String[] settings = new String(Base64.getDecoder().decode(base64txt)).split(","); + ClassPathResource cpr = new ClassPathResource("./static/"); + + // SECURITY FIX: Instead of using user-provided filename, generate a secure filename + // Option 1: Generate UUID-based filename + String userIdentifier = getUserIdentifier(request); + String secureFilename = UUID.randomUUID().toString() + ".settings"; + + // Option 2: Content-addressed storage approach + String[] settingsArr = Arrays.copyOfRange(settings, 1, settings.length); + String settingsContent = String.join("\n", settingsArr); + String contentHash = DigestUtils.sha256Hex(settingsContent); + String contentAddressedFilename = contentHash + ".settings"; + + // Use the content-addressed filename for stronger security + Path storageRoot = Paths.get(cpr.getPath()).normalize(); + Path secureStoragePath = storageRoot.resolve(contentAddressedFilename).normalize(); + File file = secureStoragePath.toFile(); + + if (!file.exists()) { + file.getParentFile().mkdirs(); + } + + // Write the settings content to the secure file location + FileOutputStream fos = new FileOutputStream(file, true); + fos.write(settingsContent.getBytes()); + fos.write(("\n" + cookie[cookie.length - 1]).getBytes()); + fos.close(); + + // Store mapping for future reference (in production, this would save to database) + storeUserSettingsMapping(userIdentifier, contentAddressedFilename); + + httpResponse.getOutputStream().println("Settings Saved"); + } + + // Helper method to get user identifier from the request + private String getUserIdentifier(WebRequest request) { + // In a real implementation, this would extract authenticated user information + // For example: return userService.getCurrentUserId(request); + return request.getRemoteUser() != null ? request.getRemoteUser() : "anonymous"; + } + + // Helper method to store user-to-filename mapping + private void storeUserSettingsMapping(String userIdentifier, String filename) { + // In a real implementation, this would store the mapping in a database + // For example: userSettingsRepository.saveMapping(userIdentifier, filename); + System.out.println("Stored mapping: " + userIdentifier + " -> " + filename); + }