Database Credentials Hardcoded in Java Source Code

Critical Risk Secrets Exposure
javadatabasecredentialshardcoded-passwordsjdbcconnection-stringsspring-boothibernate

What it is

A critical security vulnerability where database connection credentials including usernames, passwords, connection strings, and database URLs are hardcoded directly in Java source code. This exposes sensitive database access information to anyone with access to the codebase, version control history, or compiled bytecode, potentially leading to unauthorized database access and data breaches.

// VULNERABLE: Hardcoded database credentials

// application.properties
spring.datasource.url=jdbc:postgresql://prod-db:5432/app_db
spring.datasource.username=app_admin
spring.datasource.password=ProductionDBPassword123!

// DatabaseConfig.java
@Configuration
public class DatabaseConfig {
    
    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        
        // VULNERABLE: All credentials hardcoded
        dataSource.setJdbcUrl("jdbc:postgresql://prod-db:5432/app_db");
        dataSource.setUsername("app_admin");
        dataSource.setPassword("ProductionDBPassword123!");
        
        return dataSource;
    }
}

// ConnectionManager.java
public class ConnectionManager {
    // VULNERABLE: Hardcoded credentials in code
    private static final String DB_URL = "jdbc:postgresql://prod-db:5432/app_db";
    private static final String DB_USER = "app_admin";
    private static final String DB_PASSWORD = "ProductionDBPassword123!";
    
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
    }
}
// SECURE: Environment variables for database credentials

// application.yml
spring:
  datasource:
    url: ${DATABASE_URL}
    username: ${DATABASE_USERNAME}
    password: ${DATABASE_PASSWORD}

// DatabaseConfig.java
@Configuration
public class DatabaseConfig {
    
    @Value("${spring.datasource.url}")
    private String dbUrl;
    
    @Value("${spring.datasource.username}")
    private String dbUsername;
    
    @Value("${spring.datasource.password}")
    private String dbPassword;
    
    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        
        // SECURE: Credentials from environment variables
        dataSource.setJdbcUrl(dbUrl);
        dataSource.setUsername(dbUsername);
        dataSource.setPassword(dbPassword);
        
        return dataSource;
    }
}

// ConnectionManager.java
public class ConnectionManager {
    // SECURE: Credentials from environment
    private static final String DB_URL = System.getenv("DATABASE_URL");
    private static final String DB_USER = System.getenv("DATABASE_USERNAME");
    private static final String DB_PASSWORD = System.getenv("DATABASE_PASSWORD");
    
    public static Connection getConnection() throws SQLException {
        if (DB_URL == null || DB_USER == null || DB_PASSWORD == null) {
            throw new IllegalStateException("Database credentials not configured");
        }
        return DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
    }
}

💡 Why This Fix Works

The vulnerable code embeds database credentials directly in configuration files and Java classes. The secure version uses environment variables, proper Spring configuration, and includes validation and health checking without exposing sensitive information.

// VULNERABLE: Hardcoded credentials in connection pooling

// ConnectionManager.java
public class ConnectionManager {
    
    // VULNERABLE: Hardcoded database credentials
    private static final String DB_URL = "jdbc:oracle:thin:@prod-db.company.com:1521:ORCL";
    private static final String DB_USERNAME = "PROD_APP_USER";
    private static final String DB_PASSWORD = "OraclePassword2024!";
    
    private static HikariDataSource dataSource;
    
    static {
        // VULNERABLE: Static initialization with hardcoded credentials
        dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(DB_URL);
        dataSource.setUsername(DB_USERNAME);
        dataSource.setPassword(DB_PASSWORD);
        dataSource.setMaximumPoolSize(50);
    }
    
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
    
    // VULNERABLE: Debug method exposes credentials
    public static void logConnectionDetails() {
        System.out.println("Database: " + DB_URL);
        System.out.println("User: " + DB_USERNAME + "/" + DB_PASSWORD);
    }
}
// SECURE: Environment-based credential management

// ConnectionManager.java
public class ConnectionManager {
    
    // SECURE: Credentials from environment variables
    private static final String DB_URL = System.getenv("DATABASE_URL");
    private static final String DB_USERNAME = System.getenv("DATABASE_USERNAME");
    private static final String DB_PASSWORD = System.getenv("DATABASE_PASSWORD");
    
    private static HikariDataSource dataSource;
    
    static {
        if (DB_URL == null || DB_USERNAME == null || DB_PASSWORD == null) {
            throw new IllegalStateException("Database credentials not configured. " +
                "Set DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD environment variables.");
        }
        
        // SECURE: Initialize with environment credentials
        dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(DB_URL);
        dataSource.setUsername(DB_USERNAME);
        dataSource.setPassword(DB_PASSWORD);
        dataSource.setMaximumPoolSize(50);
    }
    
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
    
    // SECURE: Logging without exposing credentials
    public static void logConnectionDetails() {
        System.out.println("Database connection pool initialized");
        System.out.println("Active connections: " + dataSource.getHikariPoolMXBean().getActiveConnections());
    }
}

💡 Why This Fix Works

The vulnerable legacy code hardcodes multiple database credentials in static fields and exposes them in debug methods. The secure version implements proper credential management using environment variables, connection pooling with monitoring, and secure diagnostics without credential exposure.

Why it happens

Developers often hardcode database credentials directly in JDBC connection strings within Java classes. This commonly occurs in data access objects (DAOs), connection factory classes, or configuration classes where database URLs containing usernames and passwords are defined as string literals, making them visible in source code and compiled bytecode.

Root causes

JDBC Connection Strings with Embedded Credentials

Developers often hardcode database credentials directly in JDBC connection strings within Java classes. This commonly occurs in data access objects (DAOs), connection factory classes, or configuration classes where database URLs containing usernames and passwords are defined as string literals, making them visible in source code and compiled bytecode.

Preview example – JAVA
// VULNERABLE: Database credentials in JDBC URL
public class DatabaseConnection {
    private static final String DB_URL = "jdbc:mysql://prod-db.company.com:3306/app_database?user=admin&password=AdminPass123!";
    private static final String USERNAME = "db_admin";
    private static final String PASSWORD = "SuperSecretPassword123!";
    
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(DB_URL, USERNAME, PASSWORD);
    }
}

Spring Boot Configuration with Hardcoded Properties

Spring Boot applications frequently contain hardcoded database credentials in application.properties, application.yml files, or Java configuration classes. These credentials are often embedded in @Value annotations, @ConfigurationProperties classes, or DataSource bean definitions, making them accessible through the compiled application and configuration files.

Preview example – JAVA
// VULNERABLE: Spring Boot configuration with hardcoded credentials
@Configuration
public class DatabaseConfig {
    
    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:postgresql://prod-db:5432/company_app");
        dataSource.setUsername("prod_user");
        dataSource.setPassword("ProductionPassword2024!"); // Hardcoded!
        dataSource.setMaximumPoolSize(20);
        return dataSource;
    }
}

ORM Framework Configuration with Embedded Secrets

Object-Relational Mapping frameworks like Hibernate often have their database credentials hardcoded in configuration files or Java configuration classes. Hibernate.cfg.xml files, persistence.xml files, or programmatic configuration often contain database passwords and connection details that are committed to version control along with the application code.

Preview example – JAVA
// VULNERABLE: Hibernate programmatic configuration
public class HibernateUtil {
    private static SessionFactory sessionFactory;
    
    static {
        try {
            Configuration configuration = new Configuration();
            configuration.setProperty("hibernate.connection.driver_class", "com.mysql.cj.jdbc.Driver");
            configuration.setProperty("hibernate.connection.url", "jdbc:mysql://db-prod.internal:3306/app_db");
            configuration.setProperty("hibernate.connection.username", "hibernate_user");
            configuration.setProperty("hibernate.connection.password", "HibernatePass2024!"); // Exposed!
            
            sessionFactory = configuration.buildSessionFactory();
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }
}

Fixes

1

Use Environment Variables for Database Configuration

Replace hardcoded database credentials with environment variables that are read at runtime. Use System.getenv() or Spring's @Value with ${} placeholders to inject environment-based configuration. This keeps sensitive credentials out of source code and allows different credentials for different environments without code changes.

View implementation – JAVA
// SECURE: Using environment variables
public class DatabaseConnection {
    private static final String DB_URL = System.getenv("DATABASE_URL");
    private static final String USERNAME = System.getenv("DB_USERNAME");
    private static final String PASSWORD = System.getenv("DB_PASSWORD");
    
    public static Connection getConnection() throws SQLException {
        if (DB_URL == null || USERNAME == null || PASSWORD == null) {
            throw new IllegalStateException("Database configuration not found in environment variables");
        }
        return DriverManager.getConnection(DB_URL, USERNAME, PASSWORD);
    }
}

// Spring Boot secure configuration
@Configuration
public class DatabaseConfig {
    @Value("${database.url}")
    private String databaseUrl;
    
    @Value("${database.username}")
    private String username;
    
    @Value("${database.password}")
    private String password;
}
2

Implement External Configuration Management

Use external configuration management systems like Spring Cloud Config, Consul, or cloud provider configuration services. These systems provide centralized, encrypted configuration management with access controls and audit logging. Integrate these services to fetch database credentials at application startup without storing them in code.

View implementation – JAVA
// Using Spring Cloud Config for secure configuration
@RestController
@RefreshScope  // Allows configuration refresh without restart
public class ConfigurableService {
    
    @Value("${database.url}")
    private String databaseUrl;
    
    @Value("${database.credentials.username}")
    private String dbUsername;
    
    @Value("${database.credentials.password}")
    private String dbPassword;
}

// application.yml - points to config server
spring:
  cloud:
    config:
      uri: https://config-server.company.com
      name: myapp
      profile: production
      
// Configuration retrieved from external source at runtime
3

Use Connection Pooling with Secure Credential Management

Implement connection pooling solutions like HikariCP or Apache DBCP2 with secure credential management. Use JNDI lookups, credential providers, or integration with secret management systems. Configure connection pools to retrieve credentials from secure sources rather than embedding them in configuration files.

View implementation – JAVA
// Secure HikariCP configuration with credential provider
@Configuration
public class SecureDatabaseConfig {
    
    @Autowired
    private CredentialProvider credentialProvider;
    
    @Bean
    public DataSource dataSource() {
        DatabaseCredentials creds = credentialProvider.getDatabaseCredentials("production-db");
        
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(System.getenv("DATABASE_URL"));
        config.setUsername(creds.getUsername());
        config.setPassword(creds.getPassword());
        config.setMaximumPoolSize(20);
        config.setConnectionTimeout(30000);
        config.setIdleTimeout(600000);
        config.setMaxLifetime(1800000);
        
        return new HikariDataSource(config);
    }
}

// Custom credential provider interface
public interface CredentialProvider {
    DatabaseCredentials getDatabaseCredentials(String identifier);
}

// Implementation using AWS Secrets Manager
@Component
public class AWSSecretsCredentialProvider implements CredentialProvider {
    private final AWSSecretsManager secretsManager;
    
    @Override
    public DatabaseCredentials getDatabaseCredentials(String identifier) {
        GetSecretValueRequest request = new GetSecretValueRequest()
            .withSecretId(identifier);
        GetSecretValueResult result = secretsManager.getSecretValue(request);
        
        // Parse JSON secret and return credentials
        return parseCredentials(result.getSecretString());
    }
}

Detect This Vulnerability in Your Code

Sourcery automatically identifies database credentials hardcoded in java source code and many other security issues in your codebase.