Aufrufbares Element mit unzureichender Verhaltenszusammenfassung

Beschreibung

Aufrufbares Element mit unzureichender Verhaltenszusammenfassung tritt auf, wenn Code eine Funktion oder Methode enthält, deren Signatur und/oder zugehörige Inline-Dokumentation die Eingaben, Ausgaben, Seiteneffekte, Annahmen oder Rückgabecodes des aufrufbaren Elements nicht ausreichend beschreibt. Ohne angemessene Verhaltensdokumentation können Entwickler, die die Funktion verwenden, diese falsch einsetzen, was zu Bugs, Sicherheitslücken oder unerwartetem Verhalten führt. Dies ist besonders kritisch für sicherheitssensitive Funktionen, bei denen Aufrufer Vorbedingungen, Nachbedingungen und Fehlerbehandlungsanforderungen verstehen müssen.

Risiko

Unzureichende Verhaltenszusammenfassungen haben indirekte Sicherheitsauswirkungen. Aufrufer validieren möglicherweise Eingaben nicht ordnungsgemäß, wenn Anforderungen nicht dokumentiert sind. Rückgabecodes, die Fehler oder Sicherheitsprobleme anzeigen, können ignoriert werden. Seiteneffekte, die den Sicherheitszustand beeinflussen, werden möglicherweise nicht antizipiert. Annahmen über Thread-Sicherheit oder Reentrancy können verletzt werden. Anforderungen an die Ressourcenbereinigung werden möglicherweise nicht verstanden. Sicherheitskritische Vorbedingungen werden möglicherweise nicht erfüllt. Fehlerbehandlungspfade werden möglicherweise falsch implementiert. Funktionen werden möglicherweise aufgrund fehlender Nutzungsanleitungen in unsicheren Kontexten aufgerufen.

Lösung

Dokumentieren Sie alle Funktionsparameter mit Typen, gültigen Bereichen und Einschränkungen. Dokumentieren Sie Rückgabewerte einschließlich aller möglichen Rückgabecodes und deren Bedeutung. Geben Sie Seiteneffekte explizit an (Dateisystem-, Netzwerk-, globale Zustandsänderungen). Dokumentieren Sie Vorbedingungen, die vor dem Aufruf erfüllt sein müssen. Dokumentieren Sie Nachbedingungen, die nach dem Aufruf garantiert sind. Spezifizieren Sie Thread-Sicherheits-Eigenschaften. Dokumentieren Sie Exceptions, die geworfen werden können, und wann. Fügen Sie sicherheitsrelevante Warnungen hinzu. Stellen Sie Nutzungsbeispiele bereit. Halten Sie die Dokumentation mit der Implementierung synchron. Verwenden Sie Dokumentationsgenerierungstools (Javadoc, Doxygen, Sphinx).

Häufige Auswirkungen

AuswirkungDetails
SonstigesBereich: Sonstiges

Reduzierte Wartbarkeit -- Macht es schwieriger, das Produkt zu warten, was die Sicherheit indirekt beeinträchtigt, indem es schwieriger oder zeitaufwändiger wird, Schwachstellen zu finden und zu beheben.
IntegritätBereich: Integrität

Unsachgemäße Verwendung -- Ohne klare Verhaltensdokumentation können Aufrufer Funktionen auf eine Weise missbrauchen, die die Sicherheit kompromittiert.

Beispielcode und Lösung

Verwundbarer Code

// Verwundbar: Funktion mit unzureichender Verhaltenszusammenfassung

public class UserService {

    // Was gibt dies bei Fehler zurück? null? wirft Exception?
    // Welche Eingaben sind gültig?
    // Welche Seiteneffekte hat es?
    public User authenticate(String u, String p) {
        // ...
    }

    // Was passiert wenn user null ist?
    // Welche Berechtigungen sind erforderlich?
    // Was bedeutet der int-Rückgabewert?
    public int updateUser(User user) {
        // ...
    }

    // Wirft dies bei Fehler eine Exception oder gibt null zurück?
    // Was wenn der Benutzer nicht existiert?
    // Ist dies thread-sicher?
    public User findById(long id) {
        // ...
    }

    // Was sind "options"? Welche Werte sind gültig?
    // Was passiert bei ungültigen Optionen?
    public void process(Map<String, Object> options) {
        // ...
    }

    // Welche Fehler können auftreten? Wie werden sie gemeldet?
    // Was passiert wenn die Verbindung mittendrin fehlschlägt?
    public void syncToRemote() {
        // ...
    }
}
# Verwundbar: Python-Funktionen ohne ordnungsgemäße Dokumentation

def validate(data, rules):
    # Welches Format hat data? dict? string? Objekt?
    # Welches Format haben rules? Wie werden sie angewendet?
    # Was gibt es zurück? True/False? Validierte Daten? Fehler?
    pass


def encrypt(text, key):
    # Welcher Algorithmus wird verwendet?
    # Welches Format hat der key? bytes? string? Längenanforderungen?
    # Welche Kodierung gibt es zurück?
    # Welche Fehler können auftreten?
    pass


def connect(host, opts=None):
    # Was sind gültige opts? Was ist das Standardverhalten?
    # Was gibt es zurück? Ein Verbindungsobjekt? Nichts?
    # Wie schließt man die Verbindung?
    # Welche Exceptions können ausgelöst werden?
    pass


def process_payment(amount, card):
    # Welches Format hat amount? Cent? Dollar? Decimal?
    # Welches Format hat card? dict? Objekt? string?
    # Was passiert bei Fehler?
    # Ist die Belastung atomar?
    pass
// Verwundbar: C-Funktionen ohne Verhaltensdokumentation

// Was ist die maximale Länge? Was passiert bei Overflow?
// Wird dies null-terminiert? Wem gehört der Speicher?
char* copy_string(char* dest, char* src);

// Rückgabewerte: -1 Fehler? 0 Erfolg? Oder umgekehrt?
// Welche Fehler sind möglich? Wie bekommt man Fehlerdetails?
int process_data(void* data, int len);

// Gibt dies den Pointer frei? Setzt es ihn auf NULL?
// Kann man dies mehrfach sicher aufrufen?
void cleanup(void* resource);

// Was passiert bei NULL-Callback?
// Wann wird der Callback aufgerufen? Auf welchem Thread?
// Was ist die Lebensdauer von user_data?
void register_callback(void (*cb)(int), void* user_data);
// Verwundbar: JavaScript mit unzureichender Dokumentation

// Was ist config? Welche Eigenschaften werden erwartet?
// Was gibt es zurück? Promise? Wert? undefined?
function initialize(config) {
    // ...
}

// Bereinigt dies? Kodiert? Validiert?
// Welche Eingaben gelten als "sicher"?
function processUserInput(input) {
    // ...
}

// Wie sollen Fehler behandelt werden?
// Welches Format hat die Antwort?
// Gibt es Rate-Limits?
async function fetchData(url, options) {
    // ...
}

// Was sind die gültigen Operationen?
// Was ist der Rückgabetyp?
// Ändert dies den globalen Zustand?
function execute(operation, params) {
    // ...
}

Sichere Lösung

// Behoben: Vollständige Verhaltensdokumentation

public class UserService {

    /**
     * Authentifiziert einen Benutzer mit Benutzername und Passwort.
     *
     * <p>Validiert die bereitgestellten Anmeldedaten gegen den Benutzerspeicher
     * und gibt den authentifizierten Benutzer zurück, wenn erfolgreich.
     *
     * <p><strong>Sicherheit:</strong> Fehlgeschlagene Versuche werden protokolliert
     * und ratenlimitiert. Passwörter werden mittels zeitkonstantem Vergleich geprüft.
     *
     * @param username Der Benutzername, darf nicht null sein und 1-50 Zeichen.
     *                 Groß-/Kleinschreibung wird nicht beachtet.
     * @param password Das Klartext-Passwort, darf nicht null sein.
     *                 Wird nicht protokolliert oder gespeichert.
     * @return Das authentifizierte User-Objekt mit befülltem Session-Token
     * @throws IllegalArgumentException wenn username oder password null ist
     * @throws AuthenticationException wenn Anmeldedaten ungültig sind
     * @throws AccountLockedException wenn Konto aufgrund fehlgeschlagener Versuche gesperrt ist
     * @throws RateLimitException wenn zu viele Versuche in kurzer Zeit
     *
     * @see #logout(User) zum Beenden der Session
     * @see User#getSessionToken() für den generierten Token
     */
    public User authenticate(String username, String password)
            throws AuthenticationException, AccountLockedException, RateLimitException {
        // ...
    }

    /**
     * Aktualisiert Benutzerprofilinformationen.
     *
     * <p>Aktualisiert das Benutzerprofil in der Datenbank. Nur Nicht-Null-Felder
     * im bereitgestellten User-Objekt werden aktualisiert (partielle Aktualisierung).
     *
     * <p><strong>Thread-Sicherheit:</strong> Diese Methode ist thread-sicher.
     * Gleichzeitige Aktualisierungen desselben Benutzers werden serialisiert.
     *
     * <p><strong>Berechtigungen:</strong> Aufrufer muss UPDATE_USER-Berechtigung haben
     * oder das eigene Profil aktualisieren.
     *
     * @param user Der Benutzer mit aktualisierten Feldern. Darf nicht null sein.
     *             Die user.id muss einem existierenden Benutzer entsprechen.
     * @return Anzahl der geänderten Felder:
     *         <ul>
     *           <li>0 = Keine Änderungen (Werte gleich wie existierende)</li>
     *           <li>1+ = Anzahl aktualisierter Felder</li>
     *           <li>-1 = Benutzer nicht gefunden</li>
     *         </ul>
     * @throws IllegalArgumentException wenn user null oder user.id null ist
     * @throws PermissionDeniedException wenn Aufrufer erforderliche Berechtigungen fehlen
     * @throws ValidationException wenn Feldwerte ungültig sind
     */
    public int updateUser(User user)
            throws PermissionDeniedException, ValidationException {
        // ...
    }

    /**
     * Findet einen Benutzer anhand seiner eindeutigen ID.
     *
     * <p><strong>Thread-Sicherheit:</strong> Thread-sicher für gleichzeitige Lesezugriffe.
     *
     * @param id Die eindeutige Benutzer-ID. Muss positiv sein.
     * @return Der Benutzer wenn gefunden, oder null wenn kein Benutzer mit dieser ID existiert.
     *         Der zurückgegebene Benutzer ist eine losgelöste Kopie; Änderungen beeinflussen
     *         nicht den gespeicherten Benutzer.
     * @throws IllegalArgumentException wenn id kleiner als 1 ist
     */
    public User findById(long id) {
        // ...
    }
}
# Behoben: Python mit umfassender Dokumentation

def validate(data: dict, rules: list[ValidationRule]) -> ValidationResult:
    """
    Validiert Daten-Dictionary gegen einen Satz von Validierungsregeln.

    Wendet jede Regel auf die Daten an und sammelt Validierungsfehler.
    Regeln werden in Reihenfolge angewendet; alle Regeln werden ausgewertet,
    auch wenn frühere fehlschlagen.

    Args:
        data: Dictionary von Feldnamen zu Werten zur Validierung.
              Alle Werte müssen JSON-serialisierbare Typen sein.
        rules: Liste von ValidationRule-Objekten, die Einschränkungen definieren.
               Leere Liste ist gültig (gibt Erfolg ohne Prüfungen zurück).

    Returns:
        ValidationResult enthaltend:
        - is_valid: True wenn alle Regeln bestanden, False andernfalls
        - errors: Liste von ValidationError für jede fehlgeschlagene Regel
        - validated_data: Kopie der Daten mit angewendeten Typkonvertierungen

    Raises:
        TypeError: Wenn data kein dict oder rules keine Liste ist
        ValueError: Wenn eine Regel fehlerhaft ist

    Beispiel:
        >>> rules = [Required('name'), MaxLength('name', 50)]
        >>> result = validate({'name': 'John'}, rules)
        >>> result.is_valid
        True

    Sicherheitshinweis:
        Diese Funktion bereinigt Daten NICHT für SQL oder HTML.
        Verwenden Sie SqlParameterizer oder HtmlEscaper nach der Validierung.

    Thread-Sicherheit:
        Diese Funktion ist thread-sicher und hat keine Seiteneffekte.
    """
    pass


def encrypt(
    plaintext: bytes,
    key: bytes,
    algorithm: str = 'AES-256-GCM'
) -> tuple[bytes, bytes, bytes]:
    """
    Verschlüsselt Daten mit authentifizierter Verschlüsselung.

    Verwendet den angegebenen Algorithmus mit einem zufälligen IV/Nonce.
    Der Authentifizierungs-Tag wird zur Integritätsüberprüfung eingeschlossen.

    Args:
        plaintext: Zu verschlüsselnde Daten. Maximale Größe: 64MB.
        key: Verschlüsselungsschlüssel. Muss sein:
             - 32 Bytes für AES-256-GCM (Standard)
             - 32 Bytes für ChaCha20-Poly1305
        algorithm: Verschlüsselungsalgorithmus. Unterstützte Werte:
                   - 'AES-256-GCM' (Standard, empfohlen)
                   - 'ChaCha20-Poly1305'

    Returns:
        Tuple aus (ciphertext, nonce, auth_tag):
        - ciphertext: Verschlüsselte Daten (gleiche Länge wie Klartext bei GCM)
        - nonce: Zufälliger 12-Byte-Nonce (muss mit Ciphertext gespeichert werden)
        - auth_tag: 16-Byte-Authentifizierungs-Tag

    Raises:
        ValueError: Wenn Schlüssellänge nicht den Algorithmusanforderungen entspricht
        ValueError: Wenn Algorithmus nicht unterstützt wird
        ValueError: Wenn Klartext 64MB überschreitet
        CryptoError: Wenn Verschlüsselung fehlschlägt (selten, meist Systemproblem)

    Beispiel:
        >>> key = secrets.token_bytes(32)
        >>> ciphertext, nonce, tag = encrypt(b'secret', key)
        >>> decrypt(ciphertext, key, nonce, tag)
        b'secret'

    Sicherheitshinweise:
        - Nie ein (Schlüssel, Nonce)-Paar wiederverwenden
        - Nonce und auth_tag mit Ciphertext speichern; sie sind nicht geheim
        - Schlüssel muss geheim gehalten und sicher generiert werden
    """
    pass

CVE-Beispiele

Diese CWE ist als VERBOTEN für direkte CVE-Zuordnung markiert, da sie ein Codequalitätsproblem darstellt und keine direkte Sicherheitslücke.


Verwandte CWEs

  • CWE-1078: Unangemessener Quellcode-Stil oder Formatierung (Eltern)
  • CWE-1006: Schlechte Codierungspraktiken (Kategoriemitglied)
  • CWE-1111: Unvollständige I/O-Dokumentation (verwandt)
  • CWE-1116: Ungenaue Kommentare (verwandt)

Referenzen

  1. MITRE Corporation. "CWE-1117: Callable with Insufficient Behavioral Summary." https://cwe.mitre.org/data/definitions/1117.html
  2. Javadoc Documentation Guidelines
  3. Python PEP 257 - Docstring Conventions
  4. "Clean Code" von Robert C. Martin