Use of Redundant Code

Description

Use of Redundant Code occurs when software contains multiple functions, methods, procedures, macros, or code blocks that implement identical or nearly identical logic. This code duplication creates maintenance challenges because changes or fixes must be applied to multiple locations, increasing the risk that some instances will be missed. While primarily a code quality issue, redundant code can have indirect security implications when security patches or fixes are inconsistently applied across duplicated code segments.

Risk

The primary risk is reduced maintainability that can lead to security vulnerabilities. When a security flaw is discovered in duplicated code, developers may fix one instance while overlooking others. This inconsistent patching leaves some attack vectors open. Additionally, redundant code increases the attack surface by providing multiple potential points of exploitation. Code duplication also makes security audits more difficult and time-consuming, increasing the likelihood that vulnerabilities will be missed. The complexity introduced by duplication can also mask security issues during code review.

Solution

Extract common functionality into single, reusable functions or methods. Apply the DRY (Don't Repeat Yourself) principle during development. Use static analysis tools to detect code duplication. Refactor existing duplicated code into shared utilities. Implement code review processes that flag duplication. Create shared libraries for commonly needed functionality. Use design patterns appropriately to avoid unnecessary code repetition. Ensure any security-critical code exists in exactly one location to simplify maintenance and auditing.

Common Consequences

ImpactDetails
OtherScope: Other

Reduce Maintainability - Duplicated code makes the product harder to maintain, increasing the risk of inconsistent security patches.
IntegrityScope: Integrity

Quality Degradation - Inconsistent updates to duplicated code segments can lead to reliability issues and potential security gaps.

Example Code

Vulnerable Code

// Vulnerable: Duplicated validation logic across multiple methods
public class VulnerableUserService {

    public boolean createUser(String username, String password, String email) {
        // Duplicated validation logic - Instance 1
        if (username == null || username.length() < 3 || username.length() > 50) {
            return false;
        }
        if (!username.matches("^[a-zA-Z0-9_]+$")) {
            return false;
        }
        if (password == null || password.length() < 8) {
            return false;
        }
        if (email == null || !email.contains("@")) {
            return false;
        }

        // Create user...
        return true;
    }

    public boolean updateUser(String username, String password, String email) {
        // Duplicated validation logic - Instance 2
        // If security fix is needed, might be forgotten here
        if (username == null || username.length() < 3 || username.length() > 50) {
            return false;
        }
        if (!username.matches("^[a-zA-Z0-9_]+$")) {
            return false;
        }
        if (password == null || password.length() < 8) {
            return false;
        }
        if (email == null || !email.contains("@")) {
            return false;
        }

        // Update user...
        return true;
    }

    public boolean validateUserInput(String username, String password, String email) {
        // Duplicated validation logic - Instance 3
        // Another copy that might be missed during updates
        if (username == null || username.length() < 3 || username.length() > 50) {
            return false;
        }
        if (!username.matches("^[a-zA-Z0-9_]+$")) {
            return false;
        }
        if (password == null || password.length() < 8) {
            return false;
        }
        if (email == null || !email.contains("@")) {
            return false;
        }

        return true;
    }
}
# Vulnerable: Duplicated database query construction
class VulnerableDataAccess:

    def get_user_by_id(self, user_id, connection):
        # Duplicated query pattern - Instance 1
        cursor = connection.cursor()
        query = "SELECT * FROM users WHERE id = '" + str(user_id) + "'"
        cursor.execute(query)
        return cursor.fetchone()

    def get_user_by_email(self, email, connection):
        # Duplicated query pattern - Instance 2
        # Same SQL injection vulnerability
        cursor = connection.cursor()
        query = "SELECT * FROM users WHERE email = '" + email + "'"
        cursor.execute(query)
        return cursor.fetchone()

    def get_user_by_username(self, username, connection):
        # Duplicated query pattern - Instance 3
        # If parameterization is added to one, others remain vulnerable
        cursor = connection.cursor()
        query = "SELECT * FROM users WHERE username = '" + username + "'"
        cursor.execute(query)
        return cursor.fetchone()
// Vulnerable: Duplicated error handling with security implications
class VulnerableApiClient {

    async getUser(userId) {
        try {
            const response = await fetch(`/api/users/${userId}`);
            if (!response.ok) {
                // Duplicated error handling - Instance 1
                console.log("Error fetching user:", response.status);
                console.log("Request details:", { userId, endpoint: '/api/users' });
                throw new Error(`HTTP ${response.status}`);
            }
            return response.json();
        } catch (error) {
            console.error("Full error:", error.stack);  // Leaks stack trace
            throw error;
        }
    }

    async getOrders(userId) {
        try {
            const response = await fetch(`/api/orders?user=${userId}`);
            if (!response.ok) {
                // Duplicated error handling - Instance 2
                // Same information leakage pattern
                console.log("Error fetching orders:", response.status);
                console.log("Request details:", { userId, endpoint: '/api/orders' });
                throw new Error(`HTTP ${response.status}`);
            }
            return response.json();
        } catch (error) {
            console.error("Full error:", error.stack);  // Leaks stack trace
            throw error;
        }
    }
}

Fixed Code

// Fixed: Centralized validation logic
public class FixedUserService {

    private final UserValidator validator = new UserValidator();

    public boolean createUser(String username, String password, String email) {
        // Fixed: Use single validation method
        if (!validator.validateUserInput(username, password, email)) {
            return false;
        }

        // Create user...
        return true;
    }

    public boolean updateUser(String username, String password, String email) {
        // Fixed: Same validation method used everywhere
        if (!validator.validateUserInput(username, password, email)) {
            return false;
        }

        // Update user...
        return true;
    }
}

// Fixed: Single source of truth for validation
class UserValidator {

    private static final int MIN_USERNAME_LENGTH = 3;
    private static final int MAX_USERNAME_LENGTH = 50;
    private static final int MIN_PASSWORD_LENGTH = 8;
    private static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_]+$");
    private static final Pattern EMAIL_PATTERN = Pattern.compile("^[^@]+@[^@]+\\.[^@]+$");

    public boolean validateUserInput(String username, String password, String email) {
        return validateUsername(username)
            && validatePassword(password)
            && validateEmail(email);
    }

    public boolean validateUsername(String username) {
        if (username == null) return false;
        if (username.length() < MIN_USERNAME_LENGTH) return false;
        if (username.length() > MAX_USERNAME_LENGTH) return false;
        return USERNAME_PATTERN.matcher(username).matches();
    }

    public boolean validatePassword(String password) {
        if (password == null) return false;
        if (password.length() < MIN_PASSWORD_LENGTH) return false;
        // Additional password rules can be added in ONE place
        return true;
    }

    public boolean validateEmail(String email) {
        if (email == null) return false;
        return EMAIL_PATTERN.matcher(email).matches();
    }
}
# Fixed: Centralized, parameterized query execution
class FixedDataAccess:

    def _execute_query(self, connection, query, params):
        """Single method for all database queries with proper parameterization"""
        cursor = connection.cursor()
        cursor.execute(query, params)  # Fixed: Parameterized query
        return cursor

    def get_user_by_id(self, user_id, connection):
        # Fixed: Uses centralized query method
        query = "SELECT * FROM users WHERE id = %s"
        cursor = self._execute_query(connection, query, (user_id,))
        return cursor.fetchone()

    def get_user_by_email(self, email, connection):
        # Fixed: Same secure pattern
        query = "SELECT * FROM users WHERE email = %s"
        cursor = self._execute_query(connection, query, (email,))
        return cursor.fetchone()

    def get_user_by_username(self, username, connection):
        # Fixed: Consistent security across all methods
        query = "SELECT * FROM users WHERE username = %s"
        cursor = self._execute_query(connection, query, (username,))
        return cursor.fetchone()


# Alternative: Use a query builder pattern
class SecureQueryBuilder:

    def __init__(self, table):
        self.table = table
        self.conditions = []
        self.params = []

    def where(self, field, value):
        self.conditions.append(f"{field} = %s")
        self.params.append(value)
        return self

    def execute(self, connection):
        query = f"SELECT * FROM {self.table}"
        if self.conditions:
            query += " WHERE " + " AND ".join(self.conditions)

        cursor = connection.cursor()
        cursor.execute(query, tuple(self.params))
        return cursor
// Fixed: Centralized error handling
class FixedApiClient {

    async _handleResponse(response, context) {
        if (!response.ok) {
            // Fixed: Single error handling implementation
            // Easy to update security behavior in one place
            const error = new ApiError(response.status, context);

            // Sanitized logging - no sensitive data
            console.error(`API Error: ${response.status} for ${context.operation}`);

            throw error;
        }
        return response.json();
    }

    async _fetchWithErrorHandling(url, context) {
        try {
            const response = await fetch(url);
            return this._handleResponse(response, context);
        } catch (error) {
            if (error instanceof ApiError) {
                throw error;
            }
            // Fixed: Centralized error sanitization
            console.error(`Network error for ${context.operation}`);
            throw new ApiError(0, { ...context, networkError: true });
        }
    }

    async getUser(userId) {
        // Fixed: Uses centralized error handling
        return this._fetchWithErrorHandling(
            `/api/users/${encodeURIComponent(userId)}`,
            { operation: 'getUser', resourceType: 'user' }
        );
    }

    async getOrders(userId) {
        // Fixed: Same secure pattern
        return this._fetchWithErrorHandling(
            `/api/orders?user=${encodeURIComponent(userId)}`,
            { operation: 'getOrders', resourceType: 'orders' }
        );
    }
}

class ApiError extends Error {
    constructor(status, context) {
        super(`API Error: ${status}`);
        this.status = status;
        this.context = context;
    }
}
<?php
// Fixed: Centralized input sanitization
class FixedInputHandler {

    private static $instance = null;
    private $sanitizers = [];

    private function __construct() {
        // Define sanitizers once
        $this->sanitizers = [
            'string' => fn($v) => htmlspecialchars(trim($v), ENT_QUOTES, 'UTF-8'),
            'email' => fn($v) => filter_var($v, FILTER_SANITIZE_EMAIL),
            'int' => fn($v) => filter_var($v, FILTER_SANITIZE_NUMBER_INT),
            'url' => fn($v) => filter_var($v, FILTER_SANITIZE_URL),
        ];
    }

    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function sanitize($value, $type) {
        if (!isset($this->sanitizers[$type])) {
            throw new InvalidArgumentException("Unknown sanitizer: $type");
        }
        return $this->sanitizers[$type]($value);
    }
}

// Usage - all code uses the same sanitization
class UserController {
    private $inputHandler;

    public function __construct() {
        $this->inputHandler = FixedInputHandler::getInstance();
    }

    public function createUser($data) {
        $username = $this->inputHandler->sanitize($data['username'], 'string');
        $email = $this->inputHandler->sanitize($data['email'], 'email');
        // Consistent sanitization across entire application
    }

    public function updateUser($data) {
        $username = $this->inputHandler->sanitize($data['username'], 'string');
        $email = $this->inputHandler->sanitize($data['email'], 'email');
        // Same behavior, security fixes apply everywhere
    }
}
?>

CVE Examples

This CWE is primarily a code quality issue and is marked as PROHIBITED for direct CVE mapping. However, inconsistent security patches in duplicated code have contributed to various vulnerabilities where fixes were incompletely applied.


  • CWE-710: Improper Adherence to Coding Standards (parent)
  • CWE-1006: Bad Coding Practices (category member)
  • CWE-398: Indicator of Poor Code Quality (related)

References

  1. MITRE Corporation. "CWE-1041: Use of Redundant Code." https://cwe.mitre.org/data/definitions/1041.html
  2. Martin, Robert C. "Clean Code: A Handbook of Agile Software Craftsmanship."
  3. Hunt, Andrew and Thomas, David. "The Pragmatic Programmer" - DRY Principle.