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
| Auswirkung | Details |
|---|---|
| Andere | Bereich: Ändere Reduzierte Wartbarkeit - Inkonsistenter Code ist schwerer zu verstehen und sicher zu modifizieren. |
| Andere | Bereich: Ändere Erhöhte analytische Komplexität - Sicherheitsanalyse wird mit nicht-standardmäßigem Code schwieriger. |
| Andere | Bereich: Ä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
-
MITRE Corporation. "CWE-1076: Insufficient Adherence to Expected Conventions." https://cwe.mitre.org/data/definitions/1076.html
-
Google Style Guides. https://google.github.io/styleguide/
-
PEP 8 - Style Guide for Python Code. https://peps.python.org/pep-0008/