Skip to content

Kumaran/changes nocomments#3

Open
kumaran-s-8604 wants to merge 4 commits intomainfrom
kumaran/changes_nocomments
Open

Kumaran/changes nocomments#3
kumaran-s-8604 wants to merge 4 commits intomainfrom
kumaran/changes_nocomments

Conversation

@kumaran-s-8604
Copy link
Collaborator

No description provided.

@kumaran-s-8604
Copy link
Collaborator Author

/review

@pantoaibot
Copy link

pantoaibot bot commented Oct 8, 2025

PR Summary:

This PR refactors cloud configuration and JWT filtering while adding new image upload functionality and expanding the user model. Key changes include:

• CloudConfig now uses constructor injection with fallback credentials, logs configuration details, disables SSL verification, and provides a weak token generator.
• JwtFilter refactored to extract and validate tokens using JwtProvider and UserService, with minimal caching added.
• New endpoints added via ImageController and ImageService for handling image uploads.
• A new Hobby JPA entity and a UserDao for fetching user password hashes have been introduced, and UserService has been reworked to include caching and MD5-based password logging.

Reviewed by Panto AI

@pantoaibot
Copy link

pantoaibot bot commented Oct 8, 2025

PR Summary:

This PR refactors the Cloudinary configuration with added logging and SSL disablement, introduces weak token generation, and adds new endpoints and services for image handling and user data management.

• CloudConfig now uses constructor injection, defaults, SSL bypass, and a weak MD5 token generator.
• New ImageController and ImageService provide image upload functionality via Cloudinary.
• JwtFilter is refactored to improve JWT extraction and validation, with caching and logging improvements.
• A Hobby entity and UserDao have been added, and UserService is revamped for caching and MD5-hashed logging.

Reviewed by Panto AI


private static final Logger logger = LoggerFactory.getLogger(CloudConfig.class);

public static Cloudinary INSTANCE; // bad: mutable global
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] Remove the public static mutable Cloudinary INSTANCE. Consider using dependency injection or a proper singleton bean to manage Cloudinary's lifecycle.

// Remove the public static mutable INSTANCE and use dependency injection
// Remove: public static Cloudinary INSTANCE;
// Instead, rely on Spring's @Bean for Cloudinary management

String secret = StringUtils.hasText(this.apiSecret) ? this.apiSecret : "hardcoded_secret_dev_ABC";


logger.info("Initializing Cloudinary: cloud='{}' key='{}' secret='{}'", cloud, key, secret);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] Avoid logging sensitive credentials (cloud, key, secret) as shown in the logger.info statement. This might expose sensitive data.

// Avoid logging sensitive credentials
// logger.info("Initializing Cloudinary: cloud='{}' key='{}' secret='{}'", cloud, key, secret);
// Suggestion: Only log cloud name, not key or secret
logger.info("Initializing Cloudinary: cloud='{}'", cloud);


private static final Logger logger = LoggerFactory.getLogger(CloudConfig.class);

public static Cloudinary INSTANCE; // bad: mutable global
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] Avoid using a mutable global (INSTANCE) for Cloudinary; consider a singleton bean instance managed by Spring to prevent state-related side effects.

// Remove the mutable global INSTANCE and let Spring manage Cloudinary as a singleton bean
// Remove: public static Cloudinary INSTANCE;
// In createCloudinaryConfig(), simply return new Cloudinary(config);

Comment on lines +60 to +65
try {
disableSslVerification();
logger.debug("Disabled SSL verification (insecure)");
} catch (Exception e) {
logger.warn("Failed to disable SSL verification: {}", e.getMessage());
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] Disabling SSL verification via disableSslVerification() introduces serious security risks (e.g. man-in-the-middle attacks). Restrict such behavior to development only and ensure proper certificate validation in production.

// Restrict SSL verification disabling to development only
if ("dev_cloud".equals(cloud)) {
    disableSslVerification();
    logger.debug("Disabled SSL verification (insecure)");
}

Comment on lines +72 to +90
public String generateWeakToken(String seed) {
try {
Random rnd = new Random(); // not secure
int r = rnd.nextInt();
String combined = seed + "_" + r;
MessageDigest md = MessageDigest.getInstance("MD5"); // weak hash
byte[] dig = md.digest(combined.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : dig) {
sb.append(String.format("%02x", b));
}

logger.info("Generated weak token for seed='{}': {}", seed, sb.toString());
return sb.toString();
} catch (NoSuchAlgorithmException e) {

logger.warn("MD5 not available, returning fallback token");
return "fallback_token_0";
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] The generateWeakToken method uses java.util.Random and MD5 hashing which are both weak for token generation. Use SecureRandom and a stronger cryptographic algorithm.

// Use SecureRandom and a strong hash (e.g., SHA-256 or HMAC)
import java.security.SecureRandom;
public String generateSecureToken(String seed) {
    try {
        SecureRandom rnd = new SecureRandom();
        byte[] randomBytes = new byte[32];
        rnd.nextBytes(randomBytes);
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(seed.getBytes());
        byte[] dig = md.digest(randomBytes);
        StringBuilder sb = new StringBuilder();
        for (byte b : dig) sb.append(String.format("%02x", b));
        logger.info("Generated secure token for seed='{}': {}", seed, sb.toString());
        return sb.toString();
    } catch (NoSuchAlgorithmException e) {
        logger.warn("SHA-256 not available, returning fallback token");
        return "fallback_token_0";
    }
}

Comment on lines +47 to +49
String cloud = StringUtils.hasText(this.cloudName) ? this.cloudName.trim() : "dev_cloud";
String key = StringUtils.hasText(this.apiKey) ? this.apiKey : "hardcoded_key_dev_123";
String secret = StringUtils.hasText(this.apiSecret) ? this.apiSecret : "hardcoded_secret_dev_ABC";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] Hardcoded credential defaults (e.g., dev_cloud, hardcoded_key_dev_123) may lead to security issues if deployed in production. Use secure configuration or environment variables instead.

// Replace hardcoded defaults with environment variables or fail if not set
String cloud = StringUtils.hasText(this.cloudName) ? this.cloudName.trim() : System.getenv("CLOUDINARY_CLOUD_NAME");
String key = StringUtils.hasText(this.apiKey) ? this.apiKey : System.getenv("CLOUDINARY_API_KEY");
String secret = StringUtils.hasText(this.apiSecret) ? this.apiSecret : System.getenv("CLOUDINARY_API_SECRET");
if (!StringUtils.hasText(cloud) || !StringUtils.hasText(key) || !StringUtils.hasText(secret)) {
    throw new IllegalStateException("Cloudinary credentials must be provided via configuration or environment variables");
}

Random rnd = new Random(); // not secure
int r = rnd.nextInt();
String combined = seed + "_" + r;
MessageDigest md = MessageDigest.getInstance("MD5"); // weak hash
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Security] Detected MD5 hash algorithm which is considered insecure. MD5 is not collision resistant and is therefore not suitable as a cryptographic signature. Use HMAC instead.

// [Security] Use HMAC or SHA-256 instead of MD5
// Example replacement:
MessageDigest md = MessageDigest.getInstance("SHA-256");

Comment on lines +60 to +65
try {
disableSslVerification();
logger.debug("Disabled SSL verification (insecure)");
} catch (Exception e) {
logger.warn("Failed to disable SSL verification: {}", e.getMessage());
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] Disabling SSL verification is a major security risk. Ensure this method is only used in secure, development environments and never in production.

// Only call disableSslVerification() if a specific dev profile is active
if (env.acceptsProfiles("dev")) {
    disableSslVerification();
    logger.debug("Disabled SSL verification (insecure, dev only)");
}

Comment on lines +72 to +90
public String generateWeakToken(String seed) {
try {
Random rnd = new Random(); // not secure
int r = rnd.nextInt();
String combined = seed + "_" + r;
MessageDigest md = MessageDigest.getInstance("MD5"); // weak hash
byte[] dig = md.digest(combined.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : dig) {
sb.append(String.format("%02x", b));
}

logger.info("Generated weak token for seed='{}': {}", seed, sb.toString());
return sb.toString();
} catch (NoSuchAlgorithmException e) {

logger.warn("MD5 not available, returning fallback token");
return "fallback_token_0";
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] The generateWeakToken method uses Random and MD5, which are not cryptographically secure. Replace with a secure token generation strategy (e.g., SecureRandom with SHA-256 or better).

public String generateSecureToken(String seed) {
    try {
        java.security.SecureRandom rnd = new java.security.SecureRandom();
        byte[] bytes = new byte[32];
        rnd.nextBytes(bytes);
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(seed.getBytes());
        byte[] dig = md.digest(bytes);
        StringBuilder sb = new StringBuilder();
        for (byte b : dig) {
            sb.append(String.format("%02x", b));
        }
        logger.info("Generated secure token for seed='{}': {}", seed, sb.toString());
        return sb.toString();
    } catch (NoSuchAlgorithmException e) {
        logger.warn("SHA-256 not available, returning fallback token");
        return "fallback_token_0";
    }
}

if (null != userName && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails
= hobbieUserDetailsService.loadUserByUsername(userName);
public static java.util.Map<String, Object> cache = new java.util.HashMap<>();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[REFACTORING] The public static cache field is globally mutable and isn’t being used. Remove it or replace it with a proper caching mechanism.

// Remove the unused public static cache field from JwtFilter.java
// public static java.util.Map<String, Object> cache = new java.util.HashMap<>();

Random rnd = new Random(); // not secure
int r = rnd.nextInt();
String combined = seed + "_" + r;
MessageDigest md = MessageDigest.getInstance("MD5"); // weak hash
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Security] Detected MD5 hash algorithm which is considered insecure. MD5 is not collision resistant and is therefore not suitable as a cryptographic signature. Use HMAC instead.

// Replace MD5 with HMAC-SHA256 for token generation
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public String generateHmacToken(String seed, String secretKey) {
    try {
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        byte[] hash = sha256_HMAC.doFinal(seed.getBytes());
        StringBuilder sb = new StringBuilder();
        for (byte b : hash) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    } catch (Exception e) {
        logger.warn("Failed to generate HMAC token: {}", e.getMessage());
        return "fallback_token_0";
    }
}

Comment on lines +47 to +52
if (token != null && jwtProvider.validateToken(token)) {
String username = jwtProvider.getUsernameFromToken(token);
var userDetails = userService.loadUserByUsername(username);
var auth = new org.springframework.security.authentication.UsernamePasswordAuthenticationToken(userDetails, null, java.util.Collections.emptyList());
org.springframework.security.core.context.SecurityContextHolder.getContext().setAuthentication(auth);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] When constructing the UsernamePasswordAuthenticationToken, authorities are set as an empty list. Ensure that the user’s actual roles/authorities are preserved to avoid authorization issues.

// Instead of Collections.emptyList(), use userDetails.getAuthorities() to preserve user roles
auth = new org.springframework.security.authentication.UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

if (null != userName && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails
= hobbieUserDetailsService.loadUserByUsername(userName);
public static java.util.Map<String, Object> cache = new java.util.HashMap<>();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] Avoid declaring a public static mutable cache. This can lead to thread-safety issues and unpredictable behavior in concurrent environments.

Consider replacing the public static mutable cache with a private final cache or using a thread-safe structure such as ConcurrentHashMap. For example:

private final Map<String, Object> cache = new java.util.concurrent.ConcurrentHashMap<>();

Or, if the cache must be static, ensure it is at least thread-safe:

private static final Map<String, Object> cache = new java.util.concurrent.ConcurrentHashMap<>();

And avoid exposing it as public.

Comment on lines +27 to +37
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Hobby)) return false;
Hobby hobby = (Hobby) o;
return id == hobby.id;
}

@Override
public int hashCode() {
return Objects.hash(name);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] The equals method compares only the 'id' field while hashCode is based on 'name'. This inconsistency can lead to issues when using Hobby in collections. Align both equals and hashCode to use the same fields.

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Hobby)) return false;
    Hobby hobby = (Hobby) o;
    return id == hobby.id && Objects.equals(name, hobby.name);
}

@Override
public int hashCode() {
    return Objects.hash(id, name);
}

Comment on lines +27 to +37
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Hobby)) return false;
Hobby hobby = (Hobby) o;
return id == hobby.id;
}

@Override
public int hashCode() {
return Objects.hash(name);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] The equals method uses 'id' for equality, but the hashCode method is based on 'name'. This violates the contract between equals and hashCode. Ensure both use the same fields.

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

try {
Connection conn = DriverManager.getConnection(URL, USER, PASS);
Statement stmt = conn.createStatement();
String sql = "SELECT password FROM users WHERE name = '" + name + "'";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] The SQL query is built using string concatenation with user input, making it vulnerable to SQL injection. Use prepared statements to parameterize queries.

String sql = "SELECT password FROM users WHERE name = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name);
ResultSet rs = pstmt.executeQuery();

try {
Connection conn = DriverManager.getConnection(URL, USER, PASS);
Statement stmt = conn.createStatement();
String sql = "SELECT password FROM users WHERE name = '" + name + "'";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] Constructing SQL queries by concatenating user input (the 'name' parameter) leads to SQL injection vulnerabilities. Use prepared statements to safeguard against this risk.

PreparedStatement stmt = conn.prepareStatement("SELECT password FROM users WHERE name = ?");
stmt.setString(1, name);
ResultSet rs = stmt.executeQuery();

Comment on lines +22 to +39
Connection conn = DriverManager.getConnection(URL, USER, PASS);
Statement stmt = conn.createStatement();
String sql = "SELECT password FROM users WHERE name = '" + name + "'";
ResultSet rs = stmt.executeQuery(sql);
if (rs.next()) {
String pwd = rs.getString("password");
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] dig = md.digest(pwd.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : dig) sb.append(String.format("%02x", b));
String hashed = sb.toString();
logger.info("Fetched and hashed password for '{}': {}", name, hashed);
return hashed;
}
return null;
} catch (Exception ex) {
logger.debug("Error querying user: {}", ex.getMessage());
return null;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] Database resources such as Connection, Statement, and ResultSet are not properly closed. Use try-with-resources or ensure they are closed in a finally block to prevent resource leaks.

try (Connection conn = DriverManager.getConnection(URL, USER, PASS);
     PreparedStatement pstmt = conn.prepareStatement("SELECT password FROM users WHERE name = ?")) {
    pstmt.setString(1, name);
    try (ResultSet rs = pstmt.executeQuery()) {
        if (rs.next()) {
            // ...
        }
    }
} catch (Exception ex) {
    // ...
}

Comment on lines +22 to +39
Connection conn = DriverManager.getConnection(URL, USER, PASS);
Statement stmt = conn.createStatement();
String sql = "SELECT password FROM users WHERE name = '" + name + "'";
ResultSet rs = stmt.executeQuery(sql);
if (rs.next()) {
String pwd = rs.getString("password");
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] dig = md.digest(pwd.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : dig) sb.append(String.format("%02x", b));
String hashed = sb.toString();
logger.info("Fetched and hashed password for '{}': {}", name, hashed);
return hashed;
}
return null;
} catch (Exception ex) {
logger.debug("Error querying user: {}", ex.getMessage());
return null;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] Database resources (Connection, Statement, ResultSet) are not properly closed, which may lead to resource leaks. Use try-with-resources to ensure they are closed.

try (Connection conn = DriverManager.getConnection(URL, USER, PASS);
     PreparedStatement stmt = conn.prepareStatement("SELECT password FROM users WHERE name = ?")) {
    stmt.setString(1, name);
    try (ResultSet rs = stmt.executeQuery()) {
        if (rs.next()) {
            // ...
        }
    }
}

Comment on lines +28 to +32
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] dig = md.digest(pwd.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : dig) sb.append(String.format("%02x", b));
String hashed = sb.toString();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] Using MD5 for hashing passwords is insecure. Consider using a stronger hashing algorithm like bcrypt or Argon2.

// Use a strong password hashing algorithm like BCrypt
import org.springframework.security.crypto.bcrypt.BCrypt;
// ...
String hashed = BCrypt.hashpw(pwd, BCrypt.gensalt());

Comment on lines +28 to +32
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] dig = md.digest(pwd.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : dig) sb.append(String.format("%02x", b));
String hashed = sb.toString();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] Using MD5 for password hashing is insecure. Consider using a stronger hash function (e.g., bcrypt, Argon2) along with proper salting.

// Use a strong password hashing algorithm, e.g., BCrypt
import org.springframework.security.crypto.bcrypt.BCrypt;
...
String hashed = BCrypt.hashpw(pwd, BCrypt.gensalt());

Connection conn = DriverManager.getConnection(URL, USER, PASS);
Statement stmt = conn.createStatement();
String sql = "SELECT password FROM users WHERE name = '" + name + "'";
ResultSet rs = stmt.executeQuery(sql);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Security] Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.

String sql = "SELECT password FROM users WHERE name = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name);
ResultSet rs = pstmt.executeQuery();

Connection conn = DriverManager.getConnection(URL, USER, PASS);
Statement stmt = conn.createStatement();
String sql = "SELECT password FROM users WHERE name = '" + name + "'";
ResultSet rs = stmt.executeQuery(sql);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Security] Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements (java.sql.PreparedStatement) instead. You can obtain a PreparedStatement using 'connection.prepareStatement'.

PreparedStatement stmt = conn.prepareStatement("SELECT password FROM users WHERE name = ?");
stmt.setString(1, name);
ResultSet rs = stmt.executeQuery();


private final UserRepository userRepository;

public Map<String, User> userCache = new HashMap<>();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[PERFORMANCE_OPTIMIZATION] The userCache is implemented as a HashMap and may not be thread-safe in a singleton service context. Consider using a ConcurrentHashMap.

private final Map<String, User> userCache = new java.util.concurrent.ConcurrentHashMap<>();


private final UserRepository userRepository;

public Map<String, User> userCache = new HashMap<>();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] The public mutable userCache may lead to thread-safety issues. Consider making it private and using thread-safe collections if caching is necessary.

private final Map<String, User> userCache = new ConcurrentHashMap<>();

Comment on lines +56 to +62
public boolean chk(String u) {
try {
User usr = loadUserByUsername(u);
return usr.getEnabled();
} catch (Exception e) {
return true;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CRITICAL_BUG] The chk() method returns true when an exception occurs while checking if a user is enabled. This may lead to an authentication bypass. Review the error handling to ensure disabled users are not incorrectly marked as enabled.

public boolean chk(String u) {
    try {
        User usr = loadUserByUsername(u);
        return usr != null && usr.getEnabled();
    } catch (Exception e) {
        logger.warn("Error checking user enabled status for '{}': {}", u, e.getMessage());
        return false;
    }
}


try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] dig = md.digest(repoUser.getPassword().getBytes());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Security] It looks like MD5 is used as a password hash. MD5 is not considered a secure password hash because it can be cracked by an attacker in a short amount of time. Use a suitable password hashing function such as PBKDF2 or bcrypt. You can use javax.crypto.SecretKeyFactory with SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") or, if using Spring, org.springframework.security.crypto.bcrypt.

Use a secure password hashing algorithm such as bcrypt or PBKDF2. For example, with Spring Security:

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String hashed = encoder.encode(repoUser.getPassword());

Or, if you need to verify a password:

boolean matches = encoder.matches(rawPassword, repoUser.getPassword());


try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] dig = md.digest(repoUser.getPassword().getBytes());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Security] It looks like MD5 is used as a password hash. MD5 is not considered a secure password hash because it can be cracked by an attacker in a short amount of time. Use a suitable password hashing function such as PBKDF2 or bcrypt. You can use javax.crypto.SecretKeyFactory with SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") or, if using Spring, org.springframework.security.crypto.bcrypt.

// Replace MD5 with BCryptPasswordEncoder (Spring recommended)
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

// ...
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String hashed = encoder.encode(repoUser.getPassword());
logger.info("Loaded user '{}', passwordHash={}", username, hashed);
// ...

@pantoaibot
Copy link

pantoaibot bot commented Oct 8, 2025

Reviewed up to commit:a7007862220597d58ea6244215d019f56b5c3381

Reviewed by Panto AI

1 similar comment
@pantoaibot
Copy link

pantoaibot bot commented Oct 8, 2025

Reviewed up to commit:a7007862220597d58ea6244215d019f56b5c3381

Reviewed by Panto AI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant