Ungeeigneter Quellcode-Stil oder Formatierung
Beschreibung
Ungeeigneter Quellcode-Stil oder Formatierung tritt auf, wenn Quellcode nicht den gewünschten Stil- oder Formatierungskonventionen für Einrückung, Leerzeichen, Kommentare oder andere stilistische Elemente folgt. Inkonsistente Formatierung macht Code schwerer zu lesen und zu verstehen, was die kognitive Last für Code-Review und Wartung erhöht. Obwohl Stil oberflächlich erscheinen mag, kann inkonsistente Formatierung logische Fehler verbergen und Sicherheitsschwachstellen während des Code-Reviews schwerer erkennbar machen.
Risiko
Ungeeignete Formatierung hat indirekte Sicherheitsimplikationen. Inkonsistente Einrückung kann den tatsächlichen Kontrollfluss verbergen, sodass sicherheitsrelevante Codeblöcke anders erscheinen als sie tatsächlich sind. Code-Reviewer können Schwachstellen in schlecht formatiertem Code übersehen. Copy-Paste-Fehler sind bei inkonsistenter Formatierung wahrscheinlicher. Sicherheitstools können Schwierigkeiten haben, nicht-standardmäßige Formatierung zu parsen. Irreführende Einrückung kann dazu führen, dass Entwickler das Codeverhalten falsch verstehen. Der berühmt "goto fail"-Bug (CVE-2014-1266) wurde durch irreführende Einrückung verborgen.
Lösung
Etablieren und setzen Sie Code-Stilrichtlinien für das Projekt durch. Verwenden Sie automatisierte Formatierer (Prettier, Black, clang-format, gofmt) im Entwicklungsworkflow. Konfigurieren Sie IDEs zum Formatieren beim Speichern. Verwenden Sie Pre-Commit-Hooks zum Durchsetzen der Formatierung. Fügen Sie Stilprüfungen in CI/CD-Pipelines ein. Verwenden Sie Linter zum Erkennen von Stilverletzungen. Wählen Sie etablierte Stilrichtlinien (Google, Airbnb, PEP 8) anstatt eigene zu erstellen. Dokumentieren Sie Abweichungen von Standardstilen. Verwenden Sie Editor-Konfigurationen (.editorconfig) um Konsistenz über Tools hinweg zu erhalten.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Andere | Bereich: Ändere Erhöhte analytische Komplexität - Inkonsistenter Stil macht Code schwerer zu verstehen und zu überprüfen. |
| Andere | Bereich: Ändere Reduzierte Wartbarkeit - Schlecht formatierter Code ist schwerer sicher zu modifizieren. |
| Andere | Bereich: Ändere Verbergen logischer Fehler - Irreführende Formatierung kann tatsächliches Codeverhalten verschleiern. |
Beispielcode
Anfälliger Code
// Anfällig: Irreführende Einrückung (ähnlich dem "goto fail"-Bug)
static int verify_signature(const unsigned char *sig, size_t siglen,
const unsigned char *data, size_t datalen)
{
int result = -1;
if (!sig || !data)
goto fail;
if (siglen == 0)
goto fail;
// Anfällig: Diese Zeile wird IMMER ausgeführt, aber Einrückung suggeriert
// sie ist Teil der obigen if-Anweisung
if (siglen != EXPECTED_SIZE)
goto fail;
goto fail; // WIRD IMMER Ausgeführt - Signaturprüfung umgangen!
// Dieser Code wird nie erreicht
result = perform_actual_verification(sig, data);
fail:
return result;
}
// Anfällig: Inkonsistente Formatierung verbirgt Logikfehler
public class VulnerableProcessor {
public void processRequest(Request request)
{
// Inkonsistenter Klammerstil
if(request.isAuthenticated()){
processAuthenticated(request);
}else
// Fehlende Klammern - nur erste Anweisung ist bedingt!
if (request.isAdmin())
grantAdminAccess(request);
grantFullPermissions(request); // WIRD IMMER Ausgeführt!
// Anfällig: Irreführende Einrückung
if (request.getData() != null)
validateData(request);
processData(request); // Sieht bedingt aus, ist es aber nicht!
// Inkonsistente Abstände machen Vergleich schwer lesbar
if(request.getCount()==0||request.getCount( )>100) {
// Was prüft das eigentlich?
}
}
// Methoden mit völlig unterschiedlicher Formatierung
public void methodOne(){System.out.println("one");}
public void methodTwo()
{
System.out.println("two");
}
public void methodThree() { System.out.println("three"); }
}
# Anfällig: Inkonsistente Python-Einrückung
class VulnerableAuth:
def authenticate(self, username, password):
"""Prüft Benutzeranmeldedaten."""
if username == "admin":
# 2-Leerzeichen-Einrückung
if password == "secret":
# 3-Leerzeichen-Einrückung - inkonsistent!
return True
# Tab und Leerzeichen gemischt - kann IndentationError verursachen
if self.check_db(username, password): # Tab hier!
return True
return False
def validate_input(self,input): # Kein Leerzeichen nach Komma
if input is None:
return False
if len(input)>100: # Keine Leerzeichen um Operator
return False
#Kein Leerzeichen nach Raute in Kommentar
return True
# Inkonsistente Leerzeilen zwischen Methoden
def another_method( self ): # Seltsame Abstände
"""Irgendeine Methode."""
pass
// Anfällig: Inkonsistente JavaScript-Formatierung
class VulnerableService{
constructor() {
this.data = []
} // Fehlende Semikolons
// Methode 1: K&R-Stil
processData(data) {
if (data) {
return data.map(x=>x*2) // Inkonsistente Arrow-Function-Abstände
}
}
// Methode 2: Allman-Stil
validateInput(input)
{
if (!input)
{
return false;
}
return true;
}
// Methode 3: Einzeiler-Chaos
async fetchData(id){try{const r=await fetch('/api/'+id);return r.json();}catch(e){console.log(e)}}
// Inkonsistente Anführungszeichenstile
getMessage() {
return "Hallo " + 'Welt' + `!`;
}
}
Korrigierter Code
// Korrigiert: Konsistenter Stil verhindert irreführende Einrückung
static int verify_signature(const unsigned char *sig, size_t siglen,
const unsigned char *data, size_t datalen)
{
int result = -1;
/* Korrigiert: Immer Klammern verwenden, auch für einzelne Anweisungen */
if (!sig || !data) {
goto fail;
}
if (siglen == 0) {
goto fail;
}
if (siglen != EXPECTED_SIZE) {
goto fail;
}
/* Korrigiert: Codestruktur ist jetzt klar */
result = perform_actual_verification(sig, data);
fail:
return result;
}
/* Korrigiert: Konsistente Anwendung der Stilrichtlinie */
/*
* Verwendete Stilkonventionen:
* - 4-Leerzeichen-Einrückung
* - Öffnende Klammer auf gleicher Zeile
* - Immer Klammern für if/else/while/for verwenden
* - Leerzeichen nach Schlüsselwörtern (if, while, for)
* - Kein Leerzeichen vor Funktionsaufruf-Klammern
*/
// Korrigiert: Konsistente Java-Formatierung
public class FixedProcessor {
public void processRequest(Request request) {
// Korrigiert: Konsistenter Klammerstil (K&R)
if (request.isAuthenticated()) {
processAuthenticated(request);
} else if (request.isAdmin()) {
// Korrigiert: Immer Klammern verwenden
grantAdminAccess(request);
grantFullPermissions(request);
}
// Korrigiert: Klarer Kontrollfluss
if (request.getData() != null) {
validateData(request);
processData(request);
}
// Korrigiert: Konsistente Abstände
if (request.getCount() == 0 || request.getCount() > 100) {
handleInvalidCount(request);
}
}
// Korrigiert: Konsistente Methodenformatierung
public void methodOne() {
System.out.println("one");
}
public void methodTwo() {
System.out.println("two");
}
public void methodThree() {
System.out.println("three");
}
}
/*
* Stilrichtlinie: Google Java Style
* - 4-Leerzeichen-Einrückung (keine Tabs)
* - 100-Zeichen-Zeilenlimit
* - Klammern erforderlich für alle Kontrollstrukturen
* - Eine Anweisung pro Zeile
*/
# Korrigiert: PEP-8-konformes Python
class FixedAuth:
"""Authentifizierungs-Handler nach PEP 8."""
def authenticate(self, username: str, password: str) -> bool:
"""Prüft Benutzeranmeldedaten.
Args:
username: Der zu authentifizierende Benutzername
password: Das zu verifizierende Passwort
Returns:
True wenn Authentifizierung erfolgreich, sonst False
"""
# Korrigiert: Konsistente 4-Leerzeichen-Einrückung
if username == "admin":
if password == "secret":
return True
if self.check_db(username, password):
return True
return False
def validate_input(self, user_input: str) -> bool:
"""Validiert Benutzereingabe.
Args:
user_input: Die zu validierende Eingabe
Returns:
True wenn gültig, sonst False
"""
# Korrigiert: Konsistente Abstände um Operatoren
if user_input is None:
return False
if len(user_input) > 100:
return False
# Korrigiert: Leerzeichen nach Raute in Kommentaren
return True
def another_method(self) -> None:
"""Platzhalter-Methode."""
pass
# Stil: PEP 8
# - 4-Leerzeichen-Einrückung
# - Leerzeichen um Operatoren
# - Leerzeilen zwischen Top-Level-Definitionen
# - Zwei Leerzeilen um Klassendefinitionen
// Korrigiert: Konsistente JavaScript/ES6-Formatierung
class FixedService {
constructor() {
this.data = [];
}
// Korrigiert: Konsistenter Methodenstil
processData(data) {
if (data) {
return data.map((x) => x * 2);
}
return [];
}
// Korrigiert: Konsistente Klammerplatzierung
validateInput(input) {
if (!input) {
return false;
}
return true;
}
// Korrigiert: Lesbare async-Methode
async fetchData(id) {
try {
const response = await fetch(`/api/${id}`);
return response.json();
} catch (error) {
console.error('Fetch-Fehler:', error);
throw error;
}
}
// Korrigiert: Konsistenter Anführungszeichenstil (einfache Anführungszeichen)
getMessage() {
return 'Hallo Welt!';
}
}
/*
* Stil: Airbnb JavaScript Style Guide
* - 2-Leerzeichen-Einrückung
* - Einfache Anführungszeichen für Strings
* - Semikolons erforderlich
* - Leerzeichen um Operatoren
* - Kein abschließendes Leerzeichen
*/
// ESLint- und Prettier-Konfiguration stellen Konsistenz sicher
CVE-Beispiele
- CVE-2014-1266: Apples "goto fail"-SSL-Schwachstelle wurde durch irreführende Einrückung verborgen, die eine kritische Sicherheitsumgehung als Teil des Fehlerbehandlungscodes erscheinen ließ.
Verwandte CWEs
- CWE-1076: Insufficient Adherence to Expected Conventions (Eltern)
- CWE-546: Suspicious Comment (Kind)
- CWE-547: Use of Hard-coded, Security-relevant Constants (Kind)
- CWE-1099: Inconsistent Naming Conventions for Identifiers (Kind)
Referenzen
-
MITRE Corporation. "CWE-1078: Inappropriate Source Code Style or Formatting." https://cwe.mitre.org/data/definitions/1078.html
-
Google Style Guides. https://google.github.io/styleguide/
-
PEP 8 - Style Guide for Python Code. https://peps.python.org/pep-0008/