Insufficient Isolation of Symbolic Constant Definitions
Description
Insufficient Isolation of Symbolic Constant Definitions occurs when source code uses symbolic constants without placing their definitions in a centralized or isolated location. When constants are scattered throughout the codebase rather than being organized in dedicated configuration files, headers, or classes, it becomes difficult to manage them consistently, understand their relationships, and update them safely.
Risk
Scattered constant definitions have indirect security implications. Related security constants may have inconsistent values if defined in multiple places. Finding all security-related constants for audit is difficult. Changes to security parameters may miss some definitions. Constants with similar purposes may diverge over time. Code review cannot easily verify security constant values. Configuration management is complicated by scattered definitions. Accidental shadowing of constants can cause unexpected behavior.
Solution
Centralize constant definitions in dedicated files or classes. Group related constants together logically. Use a consistent naming convention for constants. Create hierarchical organization for large projects (security constants, network constants, etc.). Use single-source-of-truth for constants that must be consistent. Apply access control to prevent accidental modification. Document the purpose and valid range of each constant. Use build-time validation to ensure constant consistency.
Common Consequences
| Impact | Details |
|---|---|
| Other | Scope: Other Reduce Maintainability - Scattered constants are harder to manage and update. |
| Integrity | Scope: Integrity Inconsistent State - Same constant defined differently in different places. |
| Other | Scope: Other Increase Analytical Complexity - Hard to audit all constant values. |
Example Code
Vulnerable Code
// Vulnerable: Constants scattered across multiple files
// File: UserValidator.java
public class UserValidator {
// Constants defined here
private static final int MIN_PASSWORD_LENGTH = 8;
private static final int MAX_PASSWORD_LENGTH = 128;
public void validatePassword(String password) {
if (password.length() < MIN_PASSWORD_LENGTH) {
throw new ValidationException("Password too short");
}
}
}
// File: RegistrationService.java
public class RegistrationService {
// Same constant defined again - may drift out of sync!
private static final int MIN_PASSWORD_LENGTH = 8;
private static final int MAX_PASSWORD_LEN = 100; // Different value!
public void register(String username, String password) {
// Using locally defined constant
if (password.length() < MIN_PASSWORD_LENGTH) {
throw new RegistrationException("Password too short");
}
}
}
// File: PasswordResetService.java
public class PasswordResetService {
// Yet another definition
private static final int MINIMUM_PASSWORD_LENGTH = 6; // Different again!
public void resetPassword(String newPassword) {
// Inconsistent validation
if (newPassword.length() < MINIMUM_PASSWORD_LENGTH) {
throw new ValidationException("Password too short");
}
}
}
// File: SecurityConfig.java
public class SecurityConfig {
// Some security constants here
public static final int MAX_LOGIN_ATTEMPTS = 5;
}
// File: AuthenticationService.java
public class AuthenticationService {
// Duplicate constant
private static final int MAX_ATTEMPTS = 3; // Different from SecurityConfig!
public void authenticate(String username, String password) {
if (failedAttempts > MAX_ATTEMPTS) {
lockAccount();
}
}
}
// File: ApiController.java
public class ApiController {
// API-related constants scattered here
private static final int API_RATE_LIMIT = 100;
private static final int API_TIMEOUT_SECONDS = 30;
}
// File: ExternalApiClient.java
public class ExternalApiClient {
// Same constants defined differently
private static final int RATE_LIMIT = 50; // Different!
private static final int TIMEOUT = 60; // Different!
}
# Vulnerable: Python with scattered constants
# File: validators/user_validator.py
MIN_PASSWORD_LENGTH = 8
MAX_PASSWORD_LENGTH = 128
def validate_password(password):
if len(password) < MIN_PASSWORD_LENGTH:
raise ValueError("Password too short")
# File: services/registration_service.py
# Same constants defined again
MIN_PASSWORD_LEN = 8
MAX_PASSWORD_LEN = 100 # Different!
def register_user(username, password):
if len(password) < MIN_PASSWORD_LEN:
raise ValueError("Password too short")
# File: services/auth_service.py
# More scattered constants
MAX_LOGIN_ATTEMPTS = 5
LOCKOUT_DURATION_MINUTES = 30
# File: api/rate_limiter.py
# API constants scattered here
RATE_LIMIT_REQUESTS = 100
RATE_LIMIT_WINDOW_SECONDS = 60
# File: api/external_client.py
# Duplicate with different values
RATE_LIMIT = 50 # Different!
TIMEOUT_SECONDS = 30
# File: models/user.py
# Model-specific constants
USERNAME_MIN_LENGTH = 3
USERNAME_MAX_LENGTH = 50
# File: handlers/user_handler.py
# Same constants duplicated
MIN_USERNAME_LEN = 3
MAX_USERNAME_LEN = 30 # Different!
// Vulnerable: C# with scattered constants
// File: Validators/PasswordValidator.cs
public class PasswordValidator
{
private const int MinLength = 8;
private const int MaxLength = 128;
public bool Validate(string password) =>
password.Length >= MinLength && password.Length <= MaxLength;
}
// File: Services/UserService.cs
public class UserService
{
// Duplicate constant with different value
private const int MinPasswordLength = 6; // Different!
private const int MaxPasswordLength = 100; // Different!
public void CreateUser(string password)
{
if (password.Length < MinPasswordLength)
throw new ArgumentException("Password too short");
}
}
// File: Controllers/AuthController.cs
public class AuthController : Controller
{
private const int MaxLoginAttempts = 5;
private const int LockoutMinutes = 15;
// ...
}
// File: Services/AuthService.cs
public class AuthService
{
// Same constant, different value
private const int MaxAttempts = 3; // Different!
// ...
}
Fixed Code
// Fixed: Centralized constant definitions
// File: constants/SecurityConstants.java
// Single source of truth for security-related constants
public final class SecurityConstants {
// Password requirements
public static final int MIN_PASSWORD_LENGTH = 8;
public static final int MAX_PASSWORD_LENGTH = 128;
public static final int PASSWORD_HISTORY_SIZE = 10;
// Authentication
public static final int MAX_LOGIN_ATTEMPTS = 5;
public static final int LOCKOUT_DURATION_MINUTES = 30;
public static final int SESSION_TIMEOUT_MINUTES = 60;
// Account security
public static final int MAX_CONCURRENT_SESSIONS = 3;
public static final int PASSWORD_EXPIRY_DAYS = 90;
// Prevent instantiation
private SecurityConstants() {
throw new UnsupportedOperationException("Constants class");
}
}
// File: constants/ValidationConstants.java
// Validation-related constants
public final class ValidationConstants {
// Username
public static final int MIN_USERNAME_LENGTH = 3;
public static final int MAX_USERNAME_LENGTH = 50;
// Email
public static final int MAX_EMAIL_LENGTH = 254; // RFC 5321
// General text
public static final int MAX_TEXT_FIELD_LENGTH = 1000;
private ValidationConstants() {}
}
// File: constants/ApiConstants.java
// API-related constants
public final class ApiConstants {
// Rate limiting
public static final int RATE_LIMIT_REQUESTS = 100;
public static final int RATE_LIMIT_WINDOW_SECONDS = 60;
// Timeouts
public static final int CONNECT_TIMEOUT_MILLIS = 5000;
public static final int READ_TIMEOUT_MILLIS = 30000;
// Pagination
public static final int DEFAULT_PAGE_SIZE = 20;
public static final int MAX_PAGE_SIZE = 100;
private ApiConstants() {}
}
// File: validators/UserValidator.java
// Uses centralized constants
public class UserValidator {
public void validatePassword(String password) {
if (password.length() < SecurityConstants.MIN_PASSWORD_LENGTH) {
throw new ValidationException(String.format(
"Password must be at least %d characters",
SecurityConstants.MIN_PASSWORD_LENGTH));
}
if (password.length() > SecurityConstants.MAX_PASSWORD_LENGTH) {
throw new ValidationException(String.format(
"Password cannot exceed %d characters",
SecurityConstants.MAX_PASSWORD_LENGTH));
}
}
public void validateUsername(String username) {
if (username.length() < ValidationConstants.MIN_USERNAME_LENGTH ||
username.length() > ValidationConstants.MAX_USERNAME_LENGTH) {
throw new ValidationException(String.format(
"Username must be between %d and %d characters",
ValidationConstants.MIN_USERNAME_LENGTH,
ValidationConstants.MAX_USERNAME_LENGTH));
}
}
}
// All other services use the same centralized constants
public class AuthenticationService {
public void authenticate(String username, String password) {
// Uses centralized constant
if (failedAttempts > SecurityConstants.MAX_LOGIN_ATTEMPTS) {
lockAccount(SecurityConstants.LOCKOUT_DURATION_MINUTES);
}
}
}
# Fixed: Python with centralized constants
# File: constants/__init__.py
# Export all constants for easy import
from .security import *
from .validation import *
from .api import *
# File: constants/security.py
"""Security-related constants. Single source of truth."""
from typing import Final
class SecurityConstants:
"""Authentication and authorization constants."""
# Password requirements
MIN_PASSWORD_LENGTH: Final[int] = 8
MAX_PASSWORD_LENGTH: Final[int] = 128
PASSWORD_HISTORY_SIZE: Final[int] = 10
# Authentication
MAX_LOGIN_ATTEMPTS: Final[int] = 5
LOCKOUT_DURATION_MINUTES: Final[int] = 30
SESSION_TIMEOUT_MINUTES: Final[int] = 60
# Token settings
ACCESS_TOKEN_EXPIRY_MINUTES: Final[int] = 15
REFRESH_TOKEN_EXPIRY_DAYS: Final[int] = 7
# File: constants/validation.py
"""Validation constants."""
from typing import Final
class ValidationConstants:
"""Input validation limits."""
# Username
MIN_USERNAME_LENGTH: Final[int] = 3
MAX_USERNAME_LENGTH: Final[int] = 50
# Email (RFC 5321)
MAX_EMAIL_LENGTH: Final[int] = 254
# General text
MAX_TEXT_LENGTH: Final[int] = 1000
MAX_DESCRIPTION_LENGTH: Final[int] = 5000
# File: constants/api.py
"""API-related constants."""
from typing import Final
class ApiConstants:
"""API configuration constants."""
# Rate limiting
RATE_LIMIT_REQUESTS: Final[int] = 100
RATE_LIMIT_WINDOW_SECONDS: Final[int] = 60
# Timeouts
CONNECT_TIMEOUT_SECONDS: Final[int] = 5
READ_TIMEOUT_SECONDS: Final[int] = 30
# Pagination
DEFAULT_PAGE_SIZE: Final[int] = 20
MAX_PAGE_SIZE: Final[int] = 100
# File: validators/user_validator.py
# Uses centralized constants
from constants import SecurityConstants, ValidationConstants
def validate_password(password: str) -> None:
"""Validate password against security requirements."""
if len(password) < SecurityConstants.MIN_PASSWORD_LENGTH:
raise ValueError(
f"Password must be at least {SecurityConstants.MIN_PASSWORD_LENGTH} characters"
)
if len(password) > SecurityConstants.MAX_PASSWORD_LENGTH:
raise ValueError(
f"Password cannot exceed {SecurityConstants.MAX_PASSWORD_LENGTH} characters"
)
def validate_username(username: str) -> None:
"""Validate username length."""
if not (ValidationConstants.MIN_USERNAME_LENGTH <= len(username) <=
ValidationConstants.MAX_USERNAME_LENGTH):
raise ValueError(
f"Username must be between {ValidationConstants.MIN_USERNAME_LENGTH} "
f"and {ValidationConstants.MAX_USERNAME_LENGTH} characters"
)
# File: services/auth_service.py
# Uses same centralized constants
from constants import SecurityConstants
def authenticate(username: str, password: str, failed_attempts: int) -> bool:
"""Authenticate user with account lockout protection."""
if failed_attempts >= SecurityConstants.MAX_LOGIN_ATTEMPTS:
lockout_account(SecurityConstants.LOCKOUT_DURATION_MINUTES)
return False
return verify_credentials(username, password)
// Fixed: C# with centralized constants
// File: Constants/SecurityConstants.cs
namespace MyApp.Constants
{
/// <summary>
/// Security-related constants. Single source of truth.
/// </summary>
public static class SecurityConstants
{
// Password requirements
public const int MinPasswordLength = 8;
public const int MaxPasswordLength = 128;
public const int PasswordHistorySize = 10;
// Authentication
public const int MaxLoginAttempts = 5;
public const int LockoutDurationMinutes = 30;
public const int SessionTimeoutMinutes = 60;
// Tokens
public const int AccessTokenExpiryMinutes = 15;
public const int RefreshTokenExpiryDays = 7;
}
}
// File: Constants/ValidationConstants.cs
namespace MyApp.Constants
{
/// <summary>
/// Input validation constants.
/// </summary>
public static class ValidationConstants
{
// Username
public const int MinUsernameLength = 3;
public const int MaxUsernameLength = 50;
// Email
public const int MaxEmailLength = 254; // RFC 5321
// General
public const int MaxTextLength = 1000;
}
}
// File: Constants/ApiConstants.cs
namespace MyApp.Constants
{
/// <summary>
/// API configuration constants.
/// </summary>
public static class ApiConstants
{
// Rate limiting
public const int RateLimitRequests = 100;
public const int RateLimitWindowSeconds = 60;
// Timeouts
public const int ConnectTimeoutMillis = 5000;
public const int ReadTimeoutMillis = 30000;
// Pagination
public const int DefaultPageSize = 20;
public const int MaxPageSize = 100;
}
}
// File: Validators/PasswordValidator.cs
// Uses centralized constants
using MyApp.Constants;
public class PasswordValidator : IValidator<string>
{
public ValidationResult Validate(string password)
{
if (password.Length < SecurityConstants.MinPasswordLength)
{
return ValidationResult.Error(
$"Password must be at least {SecurityConstants.MinPasswordLength} characters");
}
if (password.Length > SecurityConstants.MaxPasswordLength)
{
return ValidationResult.Error(
$"Password cannot exceed {SecurityConstants.MaxPasswordLength} characters");
}
return ValidationResult.Success();
}
}
// File: Services/AuthService.cs
// Uses same centralized constants
using MyApp.Constants;
public class AuthService : IAuthService
{
public async Task<AuthResult> AuthenticateAsync(
string username, string password, int failedAttempts)
{
// Uses centralized constant
if (failedAttempts >= SecurityConstants.MaxLoginAttempts)
{
await LockAccountAsync(
username,
TimeSpan.FromMinutes(SecurityConstants.LockoutDurationMinutes));
return AuthResult.AccountLocked();
}
return await VerifyCredentialsAsync(username, password);
}
}
CVE Examples
This CWE is marked as PROHIBITED for direct CVE mapping as it represents a code quality concern rather than a direct security vulnerability.
Related CWEs
- CWE-1078: Inappropriate Source Code Style or Formatting (parent)
- CWE-1006: Bad Coding Practices (category member)
- CWE-1106: Insufficient Use of Symbolic Constants (related)
References
- MITRE Corporation. "CWE-1107: Insufficient Isolation of Symbolic Constant Definitions." https://cwe.mitre.org/data/definitions/1107.html
- Martin, Robert C. "Clean Code" - Constants and Configuration.