Ungenügender Einhalt erwarteter Konventionen

Beschreibung

Ungenügender Einhalt erwarteter Konventionen tritt auf, wenn Architektur, Quellcode, Design, Dokumentation oder andere Artefakte eines Produkts nicht den erforderlichen Konventionen folgen. Konventionen umfassen Codierungsstandards, Namenskonventionen, API-Verträge, Dokumentationsanforderungen und architektonische Muster, die für ein Projekt, eine Sprache oder ein Framework etabliert sind. Wenn Konventionen nicht befolgt werden, wird der resultierende Code schwerer zu verstehen, zu warten und auf Sicherheitsprobleme zu prüfen.

Risiko

Das Verletzen von Konventionen hat indirekte Sicherheitsimplikationen. Code, der Konventionen nicht folgt, ist schwerer auf Sicherheitsschwachstellen zu prüfen. Unerwartetes Verhalten durch Konventionsverletzungen kann ausnutzbare Bedingungen schaffen. Sicherheitstools und statische Analysatoren können Schwachstellen in nicht-konventionellem Code übersehen. Andere Entwickler können falsche Annahmen basierend auf Konventionen treffen und Fehler einführen. Framework-Sicherheitsfunktionen funktionieren möglicherweise nicht korrekt, wenn Konventionen nicht befolgt werden. Inkonsistenter Code erhöht die Wahrscheinlichkeit von Copy-Paste-Fehlern, die Schwachstellen duplizieren.

Lösung

Etablieren und dokumentieren Sie Codierungskonventionen für das Projekt. Verwenden Sie Linter und statische Analysetools, um Konventionen automatisch durchzusetzen. Fügen Sie Konventionskonformität zu Code-Review-Checklisten hinzu. Verwenden Sie IDE-Konfigurationen, die Code gemäß Konventionen formatieren. Wenden Sie automatisierte Formatierung bei Commit-Hooks an. Befolgen Sie Sprach- und Framework-Konventionen (PEP 8 für Python, Google Java Style usw.). Dokumentieren Sie Ausnahmen von Konventionen und deren Begründung. Schulen Sie Entwickler in Projektkonventionen. Verwenden Sie Pair Programming, um Konventionswissen zu teilen.

Häufige Auswirkungen

AuswirkungDetails
AndereBereich: Ändere

Reduzierte Wartbarkeit - Inkonsistenter Code ist schwerer zu verstehen und sicher zu modifizieren.
AndereBereich: Ändere

Erhöhte analytische Komplexität - Sicherheitsanalyse wird mit nicht-standardmäßigem Code schwieriger.
AndereBereich: Ändere

Qualitätsverschlechterung - Konventionsverletzungen korrelieren oft mit anderen Qualitätsproblemen.

Beispielcode

Anfälliger Code

// Anfällig: Mehrere Konventionsverletzungen
public class userAccount {  // Verletzung: Klasse sollte PascalCase sein (UserAccount)

    // Verletzung: Konstanten sollten UPPER_SNAKE_CASE sein
    private static final int maxRetries = 3;

    // Verletzung: Inkonsistente Benennung - teils camelCase, teils nicht
    private String UserName;  // Sollte userName sein
    private String password_hash;  // Sollte passwordHash sein

    // Verletzung: Öffentliches Feld statt privat mit Getter
    public boolean isactive;

    // Verletzung: Methodennamen sollten camelCase-Verben sein
    private void DoSomething() {  // Sollte doSomething sein
    }

    // Verletzung: Verletzt JavaBean-Konvention
    public String GetUserName() {  // Sollte getUserName sein
        return UserName;
    }

    // Verletzung: Inkonsistenter Klammerstil
    public void authenticate(String password)
    {
        if(password == null){
            return;
        }  // Inkonsistente Abstände um Schlüsselwörter
    }

    // Verletzung: Magische Zahlen statt Konstanten
    public void setRetryLimit(int limit) {
        if (limit > 10) {  // Was ist 10? Sollte MAX_RETRY_LIMIT sein
            limit = 10;
        }
    }
}
# Anfällig: PEP-8-Verletzungen
import os,sys  # Verletzung: Imports sollten auf separaten Zeilen sein
from typing import *  # Verletzung: Wildcard-Imports

class userAccount:  # Verletzung: Klassennamen sollten PascalCase sein
    MaxRetries = 3  # Verletzung: Sollte MAX_RETRIES für Konstante sein

    def __init__(self,userName,Password):  # Verletzung: Keine Leerzeichen nach Kommas
        self.UserName = userName  # Verletzung: Sollte user_name sein
        self.__password = Password  # Verletzung: Sollte _password sein (einzelner Unterstrich)

    def GetUser(self):  # Verletzung: Sollte get_user sein (snake_case)
        return self.UserName

    def check_Password(self, pwd):  # Verletzung: Inkonsistente Benennung
        if pwd==self.__password:  # Verletzung: Keine Leerzeichen um Operatoren
            return True
        else:
            return False

    # Verletzung: Verwendung von blankem except
    def LoadData(self):
        try:
            data = readfile()
        except:  # Fängt alles einschließlich SystemExit ab!
            pass

    # Verletzung: Veränderliches Standardargument
    def add_permissions(self, perms=[]):
        self._permissions = perms
// Anfällig: .NET-Konventionsverletzungen
public class user_manager  // Verletzung: Sollte UserManager sein
{
    // Verletzung: Öffentliche Felder statt Properties
    public string userName;
    public string Password;  // Auch: Sensible Daten sollten privat sein

    // Verletzung: Inkonsistenz bei Methodenbenennung
    public void get_user() { }  // Sollte GetUser sein
    public void UpdateUser() { }  // Korrekt, aber inkonsistent mit oben

    // Verletzung: IDisposable-Pattern nicht korrekt befolgt
    public class FileHandler : IDisposable
    {
        private FileStream _file;

        public void Dispose()
        {
            _file.Close();  // Sollte Dispose-Pattern ordnungsgemäß verwenden
        }
        // Fehlend: virtual Dispose(bool), Finalizer-Berücksichtigung
    }

    // Verletzung: Async-Methodenbenennung
    public async Task loadDataAsync()  // Sollte LoadDataAsync sein (großes L)
    {
        await Task.Delay(100);
    }

    // Verletzung: Inkonsistente Parameterbenennung
    public void ProcessOrder(int OrderId, string customerName)  // Sollte orderId sein
    {
    }
}
// Anfällig: JavaScript-Konventionsverletzungen
// Verletzung: var statt const/let
var USER_TIMEOUT = 1000;

// Verletzung: Inkonsistente Groß-/Kleinschreibung
function GetUserData(userId) {  // Sollte getUserData sein
    // Verletzung: == statt === für Vergleich
    if (userId == null) {
        return;
    }
}

class userService {  // Verletzung: Sollte UserService sein
    // Verletzung: Keine Semikolons (wenn Projektkonvention sie erfordert)
    constructor() {
        this.Users = []  // Verletzung: Sollte this.users sein
    }

    // Verletzung: Inkonsistente Methodenbenennung
    async FetchUser(id) {  // Sollte fetchUser sein
        // Verletzung: Callback statt modernem async/await
        return new Promise((resolve,reject) => {  // Abstandsprobleme
            setTimeout(() => {
                resolve({id: id})
            },100)  // Abstandsprobleme
        })
    }

    // Verletzung: Modifizieren von Funktionsparametern
    processUsers(users) {
        users.push({id: 0});  // Mutieren des Eingabeparameters
        return users;
    }
}

Korrigierter Code

// Korrigiert: Befolgt Java-Konventionen
public class UserAccount {  // PascalCase für Klassennamen

    // Konstanten in UPPER_SNAKE_CASE
    private static final int MAX_RETRIES = 3;
    private static final int MAX_RETRY_LIMIT = 10;

    // Private Felder in camelCase
    private String userName;
    private String passwordHash;
    private boolean isActive;

    // Konstruktor
    public UserAccount(String userName) {
        this.userName = userName;
        this.isActive = true;
    }

    // Getter-Methoden nach JavaBean-Konvention
    public String getUserName() {
        return userName;
    }

    public boolean isActive() {
        return isActive;
    }

    // Setter-Methoden
    public void setActive(boolean active) {
        this.isActive = active;
    }

    // Methoden in camelCase mit Verb-Präfixen
    public void authenticate(String password) {
        if (password == null) {
            return;
        }
        // Authentifizierungslogik
    }

    // Verwendung benannter Konstanten
    public void setRetryLimit(int limit) {
        if (limit > MAX_RETRY_LIMIT) {
            limit = MAX_RETRY_LIMIT;
        }
        // Limit setzen
    }

    // Konsistenter Klammerstil und Abstände
    public boolean validateCredentials(String password) {
        if (password == null || password.isEmpty()) {
            return false;
        }
        return verifyPasswordHash(password);
    }
}
# Korrigiert: Befolgt PEP-8-Konventionen
import os
import sys
from typing import List, Optional


class UserAccount:
    """Benutzerkontoverwaltung nach PEP-8-Konventionen."""

    MAX_RETRIES = 3  # Klassenkonstante

    def __init__(self, user_name: str, password: str) -> None:
        """Initialisiert Benutzerkonto.

        Args:
            user_name: Der Benutzername
            password: Das Benutzerpasswort
        """
        self.user_name = user_name  # snake_case für Attribute
        self._password = password  # Einzelner Unterstrich für protected

    def get_user(self) -> str:
        """Gibt den Benutzernamen zurück."""
        return self.user_name

    def check_password(self, pwd: str) -> bool:
        """Prüft ob Passwort übereinstimmt.

        Args:
            pwd: Zu prüfendes Passwort

        Returns:
            True wenn Passwort übereinstimmt, sonst False
        """
        return pwd == self._password

    def load_data(self) -> Optional[dict]:
        """Lädt Benutzerdaten aus Datei.

        Returns:
            Benutzerdaten-Dict oder None bei Fehler
        """
        try:
            data = self._read_file()
            return data
        except FileNotFoundError:
            # Spezifische Ausnahmebehandlung
            return None
        except PermissionError:
            # Behandlung von Berechtigungsproblemen
            return None

    def add_permissions(
        self,
        perms: Optional[List[str]] = None
    ) -> None:
        """Fügt Benutzer Berechtigungen hinzu.

        Args:
            perms: Liste von Berechtigungsstrings
        """
        # Korrigiert: Veränderliches Standardargument vermeiden
        if perms is None:
            perms = []
        self._permissions = list(perms)  # Kopie erstellen
// Korrigiert: Befolgt .NET-Konventionen
public class UserManager : IDisposable
{
    // Private Felder mit Unterstrich-Präfix (gängige Konvention)
    private readonly string _connectionString;
    private bool _disposed;

    // Properties statt öffentliche Felder
    public string UserName { get; private set; }

    // Konstruktor
    public UserManager(string connectionString)
    {
        _connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
    }

    // PascalCase für öffentliche Methoden
    public User GetUser(int userId)
    {
        // Implementierung
        return null;
    }

    public void UpdateUser(User user)
    {
        // Implementierung
    }

    // Async-Methoden enden mit Async
    public async Task<Data> LoadDataAsync(CancellationToken cancellationToken = default)
    {
        await Task.Delay(100, cancellationToken);
        return new Data();
    }

    // Konsistente Parameterbenennung (camelCase)
    public void ProcessOrder(int orderId, string customerName)
    {
        // Implementierung
    }

    // Ordnungsgemäße IDisposable-Implementierung
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // Verwaltete Ressourcen freigeben
            }
            _disposed = true;
        }
    }
}
// Korrigiert: Befolgt JavaScript/ES6-Konventionen
const USER_TIMEOUT = 1000;

// Funktionsnamen in camelCase
function getUserData(userId) {
    // Strikter Gleichheitsvergleich
    if (userId === null || userId === undefined) {
        return null;
    }
    return fetchUser(userId);
}

// Klassennamen in PascalCase
class UserService {
    constructor() {
        // Eigenschaftsnamen in camelCase
        this.users = [];
        this.isInitialized = false;
    }

    // Methodennamen in camelCase
    async fetchUser(id) {
        // Modernes async/await
        await this.ensureInitialized();

        const response = await fetch(`/api/users/${id}`);
        if (!response.ok) {
            throw new Error(`Benutzer könnte nicht abgerufen werden: ${response.status}`);
        }

        return response.json();
    }

    // Eingabeparameter nicht mutieren
    processUsers(users) {
        // Neues Array erstellen statt zu mutieren
        return [...users, { id: 0 }];
    }

    // Private-Methoden-Konvention (oder # für echtes private verwenden)
    async _ensureInitialized() {
        if (!this.isInitialized) {
            await this.initialize();
        }
    }

    // Konsistente Semikolons und Abstände
    initialize() {
        this.isInitialized = true;
        return Promise.resolve();
    }
}

export { UserService, getUserData };

CVE-Beispiele

Diese CWE ist für direkte CVE-Zuordnung als VERBOTEN markiert, da sie ein Codequalitäts-/Konventionsproblem und keine direkte Sicherheitsschwachstelle darstellt.


Verwandte CWEs

  • CWE-710: Improper Adherence to Coding Standards (Eltern)
  • CWE-1078: Inappropriate Source Code Style or Formatting (Kind)
  • CWE-1225: Documentation Issues (Kategoriemitglied)

Referenzen

  1. MITRE Corporation. "CWE-1076: Insufficient Adherence to Expected Conventions." https://cwe.mitre.org/data/definitions/1076.html

  2. Google Style Guides. https://google.github.io/styleguide/

  3. PEP 8 - Style Guide for Python Code. https://peps.python.org/pep-0008/