Unangemessener Whitespace-Stil

Beschreibung

Unangemessener Whitespace-Stil tritt auf, wenn Quellcode Whitespace enthält, der im Code inkonsistent ist oder nicht den erwarteten Standards für das Produkt folgt. Dies umfasst inkonsistente Einrückung (Mischen von Tabs und Leerzeichen), variierende Anzahl von Leerzeichen für Einrückung, inkonsistente Abstände um Operatoren, unregelmäßige Zeilenlängen und nicht standardmäßige Verwendung von Leerzeilen. Inkonsistenter Whitespace macht Code schwieriger zu lesen, zu verstehen und zu warten und kann Kontrollflussprobleme verbergen, die zu Sicherheitsschwachstellen führen.

Risiko

Unangemessene Whitespace-Stile haben indirekte, aber potenziell schwerwiegende Sicherheitsimplikationen. Das bemerkenswerteste Beispiel ist die Apple "goto fail"-Schwachstelle (CVE-2014-1266), bei der inkonsistente Einrückung einen kritischen Kontrollflussbug verdeckte. Prüfer können fälschlicherweise annehmen, dass Einrückung den tatsächlichen Kontrollfluss widerspiegelt, was zu übersehenen Schwachstellen führt. Merge-Konflikte sind bei inkonsistentem Whitespace häufiger und führen möglicherweise zu Fehlern. Code-Review wird schwieriger, wenn Formatierung inkonsistent ist. Automatisierte Analysetools können inkonsistente Ergebnisse liefern. Sicherheitskritische Codeabschnitte können schwieriger zu identifizieren und ordnungsgemäß zu überprüfen sein.

Lösung

Etablieren und erzwingen Sie konsistente Whitespace-Standards im gesamten Projekt. Wählen Sie entweder Tabs oder Leerzeichen und verwenden Sie sie konsistent. Definieren Sie eine Standard-Einrückungsbreite (z.B. 2 oder 4 Leerzeichen). Verwenden Sie automatisierte Formatierer (Prettier, Black, gofmt, clang-format), um Konsistenz durchzusetzen. Konfigurieren Sie Editor-Einstellungen passend zu Projektstandards. Verwenden Sie Pre-Commit-Hooks, um Whitespace-Konsistenz zu prüfen. Verwenden Sie immer geschweifte Klammern für Kontrollstrukturen, um einrückungsbezogene Bugs zu vermeiden. Dokumentieren Sie Whitespace-Standards in Projektrichtlinien. Verwenden Sie Linting-Tools, um Whitespace-Inkonsistenzen zu erkennen. Überprüfen Sie Whitespace bei Code-Reviews.

Häufige Auswirkungen

AuswirkungDetails
AndereBereich: Ändere

Erhöhte Analysekomplexität - Prüfer könnten fälschlicherweise annehmen, dass Einrückung den tatsächlichen Kontrollfluss widerspiegelt, was die Schwachstellenerkennung erschwert.
AndereBereich: Ändere

Reduzierte Wartbarkeit - Schlechter Whitespace macht Code schwieriger zu verstehen und zu warten, was indirekt die Sicherheit beeinträchtigt.

Beispielcode

Anfälliger Code

// ANFÄLLIG: Das berühmte "goto fail"-Muster (ähnlich CVE-2014-1266)
// Inkonsistente Einrückung verbirgt kritischen Kontrollflussbug

static OSStatus
SSLVerifySignedServerKeyExchange(SSLContext *ctx, bool isRsa,
                                  SSLBuffer signedParams,
                                  uint8_t *signature, UInt16 signatureLen)
{
    OSStatus err;

    // Inkonsistente Einrückung durchgehend
    if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0)
        goto fail;
    if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
        goto fail;
        goto fail;  // KRITISCHER BUG: Dies wird immer ausgeführt wegen fehlender Klammern!
    if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
        goto fail;

    // Der Code nach dem doppelten "goto fail" ist unerreichbar
    // SSL-Zertifikatsvalidierung wird umgangen!

fail:
    SSLFreeBuffer(&signedHashes);
    SSLFreeBuffer(&hashCtx);
    return err;
}
# ANFÄLLIG: Python mit inkonsistentem Whitespace

def process_user_input(data):
    # Mix aus Tabs und Leerzeichen - verursacht IndentationError in Python 3
    # oder stille Bugs in Python 2
	if data.is_valid:  # Tab hier
        process(data)   # Leerzeichen hier

    # Inkonsistente Einrückungsebenen
    if user.is_admin:
      delete_all()      # 2 Leerzeichen
    else:
        log_attempt()     # 4 Leerzeichen

    # Inkonsistente Abstände um Operatoren
    total=price* quantity+tax
    discount = total * 0.1

    # Sicherheitsprüfung mit irreführender Einrückung
    if not authenticated:
        return error
        log_intrusion()  # Dies sieht aus als wäre es im if-Block
                         # aber Python sieht es als unerreichbaren Code
// ANFÄLLIG: JavaScript mit inkonsistentem Whitespace

function validateUser(user) {
    // Inkonsistente Einrückung
    if (user.isAdmin) {
            grantAllAccess(user);  // 12 Leerzeichen
    }
    else{  // Kein Leerzeichen vor Klammer
      revokeAccess(user);  // 6 Leerzeichen
    }

    // Irreführende Einrückung (JavaScript ignoriert Whitespace)
    if (isSecureContext)
        validateToken();
        authorizeRequest();  // WIRD IMMER Ausgeführt - nicht im if!

    // Gemischte Tabs und Leerzeichen
	if (user.authenticated) {  // Tab
        processRequest();           // Leerzeichen
    }

    // Inkonsistente Zeilenabstände
    sensitiveOperation1();sensitiveOperation2();  // Schwer zu reviewen

    sensitiveOperation3();



    sensitiveOperation4();  // Übermäßige Leerzeilen
}
// ANFÄLLIG: Java mit Whitespace-Problemen

public class VulnerablePaymentProcessor {

    // Inkonsistente Methodenabstände
    public void processPayment(Payment p){  // Kein Leerzeichen vor Klammer
        // Sicherheitsprüfung mit irreführender Einrückung
        if (p.isVerified())
            validateAmount(p);
            processTransaction(p);  // WIRD IMMER Ausgeführt - nicht im if-Block!

        // Inkonsistente Operatorabstände
        double total=p.amount*1.1+fee;
        double discount= total *0.05;

        // Lange Zeilen die schlecht umbrechen
        if (user.hasPermission("admin") && payment.isVerified() && !payment.isFlagged() && securityContext.isActive()) { doAdminStuff(); }
    }

    public void refund( Payment p ) {  // Inkonsistente Parameterabstände
        // ...
    }
}

Korrigierter Code

// SICHER: Konsistenter Whitespace und immer Klammern verwenden

static OSStatus
SSLVerifySignedServerKeyExchange(SSLContext *ctx, bool isRsa,
                                  SSLBuffer signedParams,
                                  uint8_t *signature, UInt16 signatureLen)
{
    OSStatus err;

    // Konsistente 4-Leerzeichen-Einrückung durchgehend
    // Immer Klammern für Kontrollstrukturen verwenden
    if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) {
        goto fail;
    }

    if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) {
        goto fail;
    }

    if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) {
        goto fail;
    }

    // Signatur verifizieren
    err = SSLVerifySignature(ctx, isRsa, &hashOut, signature, signatureLen);
    if (err != 0) {
        goto fail;
    }

    err = 0;  // Erfolg

fail:
    SSLFreeBuffer(&signedHashes);
    SSLFreeBuffer(&hashCtx);
    return err;
}
# SICHER: Konsistenter Python-Whitespace (PEP 8-konform)

def process_user_input(data):
    """Benutzereingabe mit ordnungsgemäßer Validierung verarbeiten."""
    # Konsistente 4-Leerzeichen-Einrückung (keine Tabs)
    if data.is_valid:
        process(data)

    # Konsistente Einrückungsebenen
    if user.is_admin:
        delete_all()
    else:
        log_attempt()

    # Konsistente Abstände um Operatoren (PEP 8)
    total = price * quantity + tax
    discount = total * 0.1

    # Klarer Kontrollfluss mit ordnungsgemäßer Struktur
    if not authenticated:
        log_intrusion()  # Klar im if-Block
        return error

    # Verarbeitung für authentifizierte Benutzer fortsetzen
    return success
// SICHER: Konsistenter JavaScript-Whitespace

function validateUser(user) {
    // Konsistente 4-Leerzeichen-Einrückung
    if (user.isAdmin) {
        grantAllAccess(user);
    } else {
        revokeAccess(user);
    }

    // Immer Klammern für Klarheit verwenden
    if (isSecureContext) {
        validateToken();
    }
    authorizeRequest();  // Klar getrennt vom if-Block

    // Konsistente Formatierung
    if (user.authenticated) {
        processRequest();
    }

    // Eine Anweisung pro Zeile für Lesbarkeit
    sensitiveOperation1();
    sensitiveOperation2();
    sensitiveOperation3();
    sensitiveOperation4();
}
// SICHER: Konsistenter Java-Whitespace

public class FixedPaymentProcessor {

    /**
     * Zahlungstransaktion verarbeiten.
     *
     * @param payment Die zu verarbeitende Zahlung
     */
    public void processPayment(Payment payment) {
        // Immer Klammern verwenden - verhindert versehentlichen Code außerhalb von Blöcken
        if (payment.isVerified()) {
            validateAmount(payment);
            processTransaction(payment);
        }

        // Konsistente Operatorabstände
        double total = payment.amount * 1.1 + fee;
        double discount = total * 0.05;

        // Lange Zeilen für Lesbarkeit umbrechen
        boolean canProcess = user.hasPermission("admin")
            && payment.isVerified()
            && !payment.isFlagged()
            && securityContext.isActive();

        if (canProcess) {
            doAdminStuff();
        }
    }

    public void refund(Payment payment) {
        // Konsistente Parameterabstände (keine extra Leerzeichen)
        // ...
    }
}

CVE-Beispiele

CVE-2014-1266 (Apple "goto fail"): Obwohl primär ein Logikfehler, machte der irreführende Whitespace/Einrückung in Apples SSL-Implementierung die doppelte "goto fail"-Anweisung schwieriger bei Code-Review zu erkennen. Der Code schien zu zeigen, dass das zweite "goto fail" in einem if-Block war, während es tatsächlich bedingungslos ausgeführt wurde, wodurch die SSL-Zertifikatsvalidierung umgangen wurde.


Verwandte CWEs

  • CWE-1078: Unangemessener Quellcode-Stil oder Formatierung (Eltern)
  • CWE-1006: Schlechte Programmierpraktiken (Kategoriemitglied)
  • CWE-1113: Unangemessener Kommentarstil (verwandt)
  • CWE-483: Falsche Blockabgrenzung (verwandt - Folge von irreführendem Whitespace)

Referenzen

  1. MITRE. "CWE-1114: Inappropriate Whitespace Style." https://cwe.mitre.org/data/definitions/1114.html

  2. CVE-2014-1266 - Apple SSL/TLS Bug

  3. PEP 8 - Style Guide für Python-Code

  4. Google Style Guides (verschiedene Sprachen)