Excessive Use of Hard-Coded Literals in Initialization
Description
Excessive Use of Hard-Coded Literals in Initialization occurs when software initializes data elements using hard-coded literal values that are not simple integers or static constant elements. This includes embedding complex strings, configuration values, format strings, regular expressions, SQL queries, or other non-trivial literals directly in code. Such hard-coding makes the code difficult to maintain, understand, and modify, as changes require locating and updating multiple occurrences throughout the codebase.
Risk
While primarily a maintainability concern, excessive hard-coded literals have indirect security implications. Scattered literals make security audits difficult because reviewers must search entire codebases for security-relevant values. Inconsistent updates when security requirements change (like strengthening password patterns) may leave some instances vulnerable. Hard-coded SQL fragments increase SQL injection risk through inconsistent parameterization. Error messages with hard-coded text may leak sensitive information. Magic strings used for authentication or authorization can be easily overlooked during security reviews.
Solution
Define literals as named constants at the class or module level. Use configuration files or resource bundles for user-visible strings. Create dedicated classes or enums for related constant groups. Use compile-time constants where possible. Extract regex patterns, SQL templates, and format strings into well-documented constants. Consider using builder patterns for complex string construction. Implement centralized message catalogs for error and log messages. Apply static analysis rules to detect excessive literal usage.
Common Consequences
| Impact | Details |
|---|---|
| Other | Scope: Other Reduce Maintainability - Scattered hard-coded literals make code modifications difficult and error-prone. |
| Other | Scope: Other Quality Degradation - Inconsistent literal values across the codebase can lead to bugs and security gaps. |
Example Code
Vulnerable Code
// Vulnerable: Excessive hard-coded literals throughout code
public class VulnerableUserService {
public void validateUser(String username, String password) {
// Vulnerable: Hard-coded regex pattern (hard to maintain/audit)
if (!username.matches("^[a-zA-Z0-9_]{3,20}$")) {
throw new ValidationException("Username must be 3-20 alphanumeric characters");
}
// Vulnerable: Hard-coded password rules scattered in code
if (password.length() < 8) {
throw new ValidationException("Password must be at least 8 characters");
}
if (!password.matches(".*[A-Z].*")) {
throw new ValidationException("Password must contain uppercase letter");
}
if (!password.matches(".*[0-9].*")) {
throw new ValidationException("Password must contain a number");
}
}
public User findUser(Connection conn, String username) throws SQLException {
// Vulnerable: Hard-coded SQL query
PreparedStatement stmt = conn.prepareStatement(
"SELECT id, username, email, created_at FROM users WHERE username = ? AND status = 'ACTIVE'"
);
stmt.setString(1, username);
// ...
}
public void sendWelcomeEmail(User user) {
// Vulnerable: Hard-coded email content
String subject = "Welcome to Our Platform!";
String body = "Dear " + user.getName() + ",\n\n" +
"Thank you for joining Our Platform. Your account has been created successfully.\n\n" +
"Please visit https://ourplatform.com/verify?token=" + user.getVerificationToken() + "\n\n" +
"Best regards,\nThe Our Platform Team";
emailService.send(user.getEmail(), subject, body);
}
public void logAction(String action, User user) {
// Vulnerable: Hard-coded log format scattered throughout
logger.info("[USER_ACTION] user=" + user.getId() + " action=" + action +
" timestamp=" + System.currentTimeMillis() + " ip=" + user.getLastIp());
}
}
# Vulnerable: Hard-coded literals everywhere
class VulnerablePaymentProcessor:
def process_payment(self, amount, card_number):
# Vulnerable: Hard-coded validation patterns
if not re.match(r'^\d{16}$', card_number):
raise ValueError("Invalid card number format")
# Vulnerable: Hard-coded amount limits
if amount < 0.01:
raise ValueError("Amount must be at least $0.01")
if amount > 10000.00:
raise ValueError("Amount cannot exceed $10,000.00")
# Vulnerable: Hard-coded API endpoint (should be config)
response = requests.post(
"https://api.paymentprovider.com/v2/charge",
json={
"amount": amount,
"card": card_number,
"merchant_id": "MER123456", # Hard-coded credential!
"currency": "USD"
},
headers={
"Authorization": "Bearer sk_live_xxxxx", # Hard-coded secret!
"Content-Type": "application/json"
}
)
# Vulnerable: Hard-coded status codes
if response.status_code == 200:
return "Payment successful"
elif response.status_code == 402:
return "Payment declined"
elif response.status_code == 429:
return "Too many requests, please try again later"
else:
return "Payment failed with error code: " + str(response.status_code)
// Vulnerable: Hard-coded literals in JavaScript
class VulnerableFormValidator {
validateForm(data) {
const errors = [];
// Vulnerable: Hard-coded patterns and messages
if (!data.email.match(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/)) {
errors.push("Please enter a valid email address");
}
if (!data.phone.match(/^\+?1?\d{10,14}$/)) {
errors.push("Phone number must be 10-14 digits");
}
if (data.age < 18 || data.age > 120) {
errors.push("Age must be between 18 and 120");
}
if (!["Mr", "Mrs", "Ms", "Dr", "Prof"].includes(data.title)) {
errors.push("Please select a valid title");
}
// Vulnerable: Hard-coded error display
if (errors.length > 0) {
document.getElementById("error-container").innerHTML =
"<div class='alert alert-danger'><ul>" +
errors.map(e => "<li>" + e + "</li>").join("") +
"</ul></div>";
}
return errors.length === 0;
}
}
Fixed Code
// Fixed: Centralized constants and configuration
public class FixedUserService {
// Fixed: Centralized validation patterns
private static final class ValidationPatterns {
static final Pattern USERNAME = Pattern.compile("^[a-zA-Z0-9_]{3,20}$");
static final Pattern HAS_UPPERCASE = Pattern.compile(".*[A-Z].*");
static final Pattern HAS_DIGIT = Pattern.compile(".*[0-9].*");
}
// Fixed: Centralized constraints
private static final class PasswordPolicy {
static final int MIN_LENGTH = 8;
static final int MAX_LENGTH = 128;
static final boolean REQUIRE_UPPERCASE = true;
static final boolean REQUIRE_DIGIT = true;
}
// Fixed: Message constants (could also be in resource bundle)
private static final class Messages {
static final String INVALID_USERNAME =
"Username must be 3-20 alphanumeric characters";
static final String PASSWORD_TOO_SHORT =
"Password must be at least " + PasswordPolicy.MIN_LENGTH + " characters";
static final String PASSWORD_NEEDS_UPPERCASE =
"Password must contain uppercase letter";
static final String PASSWORD_NEEDS_DIGIT =
"Password must contain a number";
}
// Fixed: SQL queries as constants
private static final class Queries {
static final String FIND_ACTIVE_USER =
"SELECT id, username, email, created_at FROM users " +
"WHERE username = ? AND status = ?";
}
private static final String USER_STATUS_ACTIVE = "ACTIVE";
public void validateUser(String username, String password) {
if (!ValidationPatterns.USERNAME.matcher(username).matches()) {
throw new ValidationException(Messages.INVALID_USERNAME);
}
if (password.length() < PasswordPolicy.MIN_LENGTH) {
throw new ValidationException(Messages.PASSWORD_TOO_SHORT);
}
if (PasswordPolicy.REQUIRE_UPPERCASE &&
!ValidationPatterns.HAS_UPPERCASE.matcher(password).matches()) {
throw new ValidationException(Messages.PASSWORD_NEEDS_UPPERCASE);
}
if (PasswordPolicy.REQUIRE_DIGIT &&
!ValidationPatterns.HAS_DIGIT.matcher(password).matches()) {
throw new ValidationException(Messages.PASSWORD_NEEDS_DIGIT);
}
}
public User findUser(Connection conn, String username) throws SQLException {
PreparedStatement stmt = conn.prepareStatement(Queries.FIND_ACTIVE_USER);
stmt.setString(1, username);
stmt.setString(2, USER_STATUS_ACTIVE);
// ...
}
public void sendWelcomeEmail(User user) {
// Fixed: Use template engine
EmailTemplate template = templateEngine.load("welcome-email");
template.setVariable("userName", user.getName());
template.setVariable("verificationUrl",
config.getBaseUrl() + "/verify?token=" + user.getVerificationToken());
emailService.send(user.getEmail(), template);
}
public void logAction(String action, User user) {
// Fixed: Structured logging
logger.info(LogEvent.builder()
.type("USER_ACTION")
.userId(user.getId())
.action(action)
.ip(user.getLastIp())
.build());
}
}
# Fixed: Centralized configuration and constants
from dataclasses import dataclass
from enum import Enum
import re
class PaymentConfig:
"""Centralized payment configuration"""
MIN_AMOUNT = 0.01
MAX_AMOUNT = 10000.00
DEFAULT_CURRENCY = "USD"
# Loaded from secure configuration
API_ENDPOINT = os.environ['PAYMENT_API_ENDPOINT']
MERCHANT_ID = os.environ['PAYMENT_MERCHANT_ID']
API_KEY = os.environ['PAYMENT_API_KEY']
class ValidationPatterns:
"""Centralized validation patterns"""
CARD_NUMBER = re.compile(r'^\d{16}$')
CVV = re.compile(r'^\d{3,4}$')
EXPIRY = re.compile(r'^(0[1-9]|1[0-2])\/\d{2}$')
class PaymentStatus(Enum):
"""Payment response status codes"""
SUCCESS = 200
DECLINED = 402
RATE_LIMITED = 429
class PaymentMessages:
"""User-facing payment messages"""
SUCCESS = "Payment successful"
DECLINED = "Payment declined"
RATE_LIMITED = "Too many requests, please try again later"
GENERIC_ERROR = "Payment failed"
INVALID_CARD = "Invalid card number format"
AMOUNT_TOO_LOW = f"Amount must be at least ${PaymentConfig.MIN_AMOUNT:.2f}"
AMOUNT_TOO_HIGH = f"Amount cannot exceed ${PaymentConfig.MAX_AMOUNT:,.2f}"
class FixedPaymentProcessor:
def __init__(self, config: PaymentConfig):
self.config = config
def process_payment(self, amount: float, card_number: str) -> str:
self._validate_input(amount, card_number)
response = requests.post(
self.config.API_ENDPOINT,
json={
"amount": amount,
"card": card_number,
"merchant_id": self.config.MERCHANT_ID,
"currency": self.config.DEFAULT_CURRENCY
},
headers={
"Authorization": f"Bearer {self.config.API_KEY}",
"Content-Type": "application/json"
}
)
return self._handle_response(response)
def _validate_input(self, amount: float, card_number: str):
if not ValidationPatterns.CARD_NUMBER.match(card_number):
raise ValueError(PaymentMessages.INVALID_CARD)
if amount < PaymentConfig.MIN_AMOUNT:
raise ValueError(PaymentMessages.AMOUNT_TOO_LOW)
if amount > PaymentConfig.MAX_AMOUNT:
raise ValueError(PaymentMessages.AMOUNT_TOO_HIGH)
def _handle_response(self, response) -> str:
status_messages = {
PaymentStatus.SUCCESS.value: PaymentMessages.SUCCESS,
PaymentStatus.DECLINED.value: PaymentMessages.DECLINED,
PaymentStatus.RATE_LIMITED.value: PaymentMessages.RATE_LIMITED,
}
return status_messages.get(
response.status_code,
PaymentMessages.GENERIC_ERROR
)
// Fixed: Centralized constants and patterns
const ValidationConfig = Object.freeze({
patterns: {
email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
phone: /^\+?1?\d{10,14}$/
},
constraints: {
ageMin: 18,
ageMax: 120
},
validTitles: ['Mr', 'Mrs', 'Ms', 'Dr', 'Prof']
});
const ValidationMessages = Object.freeze({
invalidEmail: 'Please enter a valid email address',
invalidPhone: 'Phone number must be 10-14 digits',
invalidAge: `Age must be between ${ValidationConfig.constraints.ageMin} and ${ValidationConfig.constraints.ageMax}`,
invalidTitle: 'Please select a valid title'
});
class FixedFormValidator {
constructor(config = ValidationConfig, messages = ValidationMessages) {
this.config = config;
this.messages = messages;
}
validateForm(data) {
const errors = [];
if (!this.config.patterns.email.test(data.email)) {
errors.push(this.messages.invalidEmail);
}
if (!this.config.patterns.phone.test(data.phone)) {
errors.push(this.messages.invalidPhone);
}
const { ageMin, ageMax } = this.config.constraints;
if (data.age < ageMin || data.age > ageMax) {
errors.push(this.messages.invalidAge);
}
if (!this.config.validTitles.includes(data.title)) {
errors.push(this.messages.invalidTitle);
}
return {
isValid: errors.length === 0,
errors
};
}
}
// Separate UI concern
class FormErrorDisplay {
static show(containerId, errors) {
const container = document.getElementById(containerId);
container.innerHTML = this.renderErrors(errors);
}
static renderErrors(errors) {
if (errors.length === 0) return '';
const items = errors.map(e => `<li>${this.escapeHtml(e)}</li>`).join('');
return `<div class="alert alert-danger"><ul>${items}</ul></div>`;
}
static escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
}
CVE Examples
This CWE describes a code quality issue. While not directly mapped to CVEs, scattered hard-coded literals have contributed to security issues when updates were inconsistently applied.
Related CWEs
- CWE-1419: Incorrect Initialization of Resource (parent)
- CWE-452: Initialization and Cleanup Errors (category member)
- CWE-547: Use of Hard-coded, Security-relevant Constants (related)
References
- MITRE Corporation. "CWE-1052: Excessive Use of Hard-Coded Literals in Initialization." https://cwe.mitre.org/data/definitions/1052.html
- Martin, Robert C. "Clean Code: A Handbook of Agile Software Craftsmanship."
- Fowler, Martin. "Refactoring: Improving the Design of Existing Code."