Abhängigkeit von Laufzeitkomponente in generiertem Code
Beschreibung
Abhängigkeit von Laufzeitkomponente in generiertem Code tritt auf, wenn automatisch generierter Code von einer bestimmten Laufzeit-Unterstützungskomponente abhängt, um ordnungsgemäß ausgeführt zu werden. Code-Generatoren, Compiler oder Entwicklungs-Frameworks können Code produzieren, der ohne bestimmte Laufzeitbibliotheken, Frameworks oder Unterstützungsmodule nicht funktionieren kann. Dies erzeugt eine enge Kopplung zwischen dem generierten Code und seiner Laufzeitumgebung, was den Code weniger portabel und schwieriger unabhängig zu warten macht.
Risiko
Die Abhängigkeit von spezifischen Laufzeitkomponenten in generiertem Code hat indirekte Sicherheitsimplikationen. Sicherheitsschwachstellen in der Laufzeitkomponente betreffen allen generierten Code. Updates der Laufzeit können generierten Code unerwartet brechen. Der generierte Code kann nicht unabhängig von der Laufzeit auditiert werden. Versionsungleichheiten zwischen generiertem Code und Laufzeit können Sicherheitsprobleme verursachen. Die Bereitstellung erfordert die Verwaltung sowohl des generierten Codes als auch der Laufzeitabhängigkeiten. Sicherheitsfixes in der Laufzeit werden möglicherweise nicht angewendet, wenn sie die Kompatibilität brechen. Die undurchsichtige Natur von generiertem Code erschwert Sicherheitsüberprüfungen.
Lösung
Minimieren Sie Abhängigkeiten von Laufzeitkomponenten in Code-Generatoren. Generieren Sie wo möglich eigenständigen Code. Dokumentieren Sie alle Laufzeitabhängigkeiten klar. Verwenden Sie stabile, gut gewartete Laufzeitkomponenten. Implementieren Sie Versionsprüfungen zwischen generiertem Code und Laufzeit. Erwägen Sie, Code zu generieren, der Standardbibliotheksfunktionen anstelle benutzerdefinierter Laufzeiten verwendet. Bieten Sie Mechanismen zur Neugenerierung von Code bei Laufzeitänderungen. Testen Sie generierten Code mit verschiedenen Laufzeitversionen. Fügen Sie Laufzeitversionanforderungen in generierte Code-Kommentare oder Metadaten ein.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Andere | Bereich: Ändere Reduzierte Wartbarkeit - Generierter Code kann nicht ohne Verständnis der Laufzeitabhängigkeiten gewartet werden. |
| Andere | Bereich: Ändere Reduzierte Portabilität - Code kann ohne spezifische Laufzeitkomponente nicht ausgeführt werden. |
| Verfügbarkeit | Bereich: Verfügbarkeit DoS: Absturz - Laufzeitversionskonflikte können Abstürze verursachen. |
Beispielcode
Anfälliger Code
// Anfällig: Generierter ORM-Code eng mit Laufzeit gekoppelt
// GENERIERTER CODE - NICHT BEARBEITEN
// Dieser Code wurde von MyORMGenerator v2.3 generiert
public class GeneratedUserRepository {
// Anfällig: Abhängig von spezifischer Laufzeitkomponente
private final MyORMRuntime runtime;
private final MyORMSession session;
public GeneratedUserRepository() {
// Anfällig: Schlägt fehl, wenn MyORMRuntime nicht verfügbar
this.runtime = MyORMRuntime.getInstance();
this.session = runtime.openSession();
}
public User findById(Long id) {
// Anfällig: Verwendet laufzeitspezifischen Abfragemechanismus
return runtime.executeQuery(
MyORMQuery.builder()
.entity(User.class)
.where("id", MyORMOperator.EQUALS, id)
.build()
).getSingleResult();
}
public List<User> findAll() {
// Anfällig: Laufzeitspezifische Paginierung
return runtime.createFinder(User.class)
.withPagination(MyORMPagination.unlimited())
.execute();
}
public void save(User user) {
// Anfällig: Laufzeit-Transaktionsverwaltung
runtime.inTransaction(() -> {
session.persist(user);
});
}
}
// Problem: Wenn MyORMRuntime-Version sich ändert oder nicht verfügbar ist,
// brechen ALLE generierten Repositories
# Anfällig: Generierter API-Client abhängig von Laufzeit
# AUTOMATISCH GENERIERTER CODE - NICHT ÄNDERN
# Generiert von APIClientGenerator v1.5
# Erfordert: api_runtime >= 2.0.0
from api_runtime import (
APIRuntimeClient,
RequestBuilder,
ResponseParser,
AuthenticationHandler,
RetryPolicy,
CircuitBreaker
)
class GeneratedUserServiceClient:
"""Generierter Client für UserService API."""
def __init__(self, base_url: str):
# Anfällig: Enge Kopplung an Laufzeit
self._client = APIRuntimeClient(
base_url=base_url,
retry_policy=RetryPolicy.default(),
circuit_breaker=CircuitBreaker.default()
)
self._auth = AuthenticationHandler.oauth2()
def get_user(self, user_id: str):
# Anfällig: Laufzeitspezifischer Request-Aufbau
request = RequestBuilder() \
.method('GET') \
.path(f'/users/{user_id}') \
.with_auth(self._auth) \
.build()
response = self._client.execute(request)
return ResponseParser.parse(response, UserDTO)
def create_user(self, user_data: dict):
# Anfällig: Laufzeit übernimmt Serialisierung
request = RequestBuilder() \
.method('POST') \
.path('/users') \
.body(user_data) \
.with_auth(self._auth) \
.content_type('application/json') \
.build()
response = self._client.execute(request)
return ResponseParser.parse(response, UserDTO)
# Problem: Upgrade von api_runtime kann alle generierten Clients brechen
# Sicherheitsfixes in api_runtime erfordern Testen aller generierten Codes
// Anfällig: Generierter Serialisierungscode mit Laufzeitabhängigkeit
// <auto-generated>
// Dieser Code wurde von SerializerGenerator v3.1 generiert
// Erfordert: MySerializer.Runtime >= 3.0
// </auto-generated>
using MySerializer.Runtime;
using MySerializer.Runtime.Attributes;
using MySerializer.Runtime.Converters;
[RuntimeSerializable]
public partial class GeneratedUserDTO
{
// Anfällig: Laufzeitspezifische Attribute
[RuntimeProperty("id", Required = true)]
public long Id { get; set; }
[RuntimeProperty("username")]
[RuntimeValidation(MinLength = 3, MaxLength = 50)]
public string Username { get; set; }
[RuntimeProperty("email")]
[RuntimeConverter(typeof(EmailConverter))]
public string Email { get; set; }
[RuntimeProperty("created_at")]
[RuntimeConverter(typeof(ISO8601DateConverter))]
public DateTime CreatedAt { get; set; }
// Anfällig: Laufzeit-generierte Serialisierung
public string Serialize()
{
return RuntimeSerializer.Serialize(this);
}
public static GeneratedUserDTO Deserialize(string json)
{
return RuntimeSerializer.Deserialize<GeneratedUserDTO>(json);
}
}
// Problem: MySerializer.Runtime-Änderungen betreffen alle generierten DTOs
// Sicherheitsschwachstellen in Convertern betreffen allen generierten Code
Korrigierter Code
// Korrigiert: Generierter Code mit minimaler Laufzeitabhängigkeit
// GENERIERTER CODE
// Generiert von ImprovedORMGenerator v3.0
// Laufzeitabhängigkeit: Optional (fällt auf Standard-JDBC zurück)
public class GeneratedUserRepository implements UserRepository {
private final DataSource dataSource;
private final Optional<ORMRuntime> runtime;
// Korrigiert: Kann mit oder ohne Laufzeit arbeiten
public GeneratedUserRepository(DataSource dataSource) {
this.dataSource = dataSource;
this.runtime = ORMRuntime.tryCreate();
}
@Override
public User findById(Long id) {
// Korrigiert: Fallback auf Standard-JDBC wenn Laufzeit nicht verfügbar
if (runtime.isPresent()) {
return runtime.get().findById(User.class, id);
}
// Eigenständige Fallback-Implementierung
return executeQuery(
"SELECT id, username, email, created_at FROM users WHERE id = ?",
ps -> ps.setLong(1, id),
this::mapUser
);
}
@Override
public List<User> findAll() {
if (runtime.isPresent()) {
return runtime.get().findAll(User.class);
}
return executeQuery(
"SELECT id, username, email, created_at FROM users",
ps -> {},
this::mapUser
);
}
@Override
public void save(User user) {
if (runtime.isPresent()) {
runtime.get().save(user);
return;
}
// Eigenständige Save-Implementierung
executeUpdate(
"INSERT INTO users (username, email, created_at) VALUES (?, ?, ?)",
ps -> {
ps.setString(1, user.getUsername());
ps.setString(2, user.getEmail());
ps.setTimestamp(3, Timestamp.from(user.getCreatedAt()));
}
);
}
// Eigenständige Hilfsmethoden
private <T> T executeQuery(String sql, PreparedStatementSetter setter,
ResultSetMapper<T> mapper) {
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
setter.set(ps);
try (ResultSet rs = ps.executeQuery()) {
// Ergebnisse mappen...
return mapper.map(rs);
}
} catch (SQLException e) {
throw new DataAccessException(e);
}
}
private User mapUser(ResultSet rs) throws SQLException {
// Eigenständiges Mapping
User user = new User();
user.setId(rs.getLong("id"));
user.setUsername(rs.getString("username"));
user.setEmail(rs.getString("email"));
user.setCreatedAt(rs.getTimestamp("created_at").toInstant());
return user;
}
}
# Korrigiert: Generierter API-Client mit optionaler Laufzeit
# AUTOMATISCH GENERIERTER CODE
# Generiert von ImprovedAPIGenerator v2.0
# Laufzeit: Optional (verwendet Standard-requests-Bibliothek als Fallback)
from typing import Optional, Any
import json
# Versuche optionale Laufzeit zu importieren, falle auf Standardbibliothek zurück
try:
from api_runtime import APIRuntimeClient
HAS_RUNTIME = True
except ImportError:
HAS_RUNTIME = False
import requests
class GeneratedUserServiceClient:
"""Generierter Client mit optionaler Laufzeitabhängigkeit."""
def __init__(self, base_url: str, api_key: Optional[str] = None):
self._base_url = base_url.rstrip('/')
self._api_key = api_key
# Korrigiert: Optionale Laufzeit
if HAS_RUNTIME:
self._client = APIRuntimeClient(base_url=base_url)
else:
self._client = None
self._session = requests.Session()
def get_user(self, user_id: str) -> dict:
"""Benutzer nach ID abrufen."""
if self._client:
# Laufzeit verwenden wenn verfügbar
return self._client.get(f'/users/{user_id}')
# Eigenständiger Fallback
response = self._session.get(
f'{self._base_url}/users/{user_id}',
headers=self._get_headers()
)
response.raise_for_status()
return response.json()
def create_user(self, user_data: dict) -> dict:
"""Neuen Benutzer erstellen."""
if self._client:
return self._client.post('/users', json=user_data)
# Eigenständiger Fallback
response = self._session.post(
f'{self._base_url}/users',
headers=self._get_headers(),
json=user_data
)
response.raise_for_status()
return response.json()
def _get_headers(self) -> dict:
"""Request-Header abrufen."""
headers = {'Content-Type': 'application/json'}
if self._api_key:
headers['Authorization'] = f'Bearer {self._api_key}'
return headers
# Alternative: Vollständig eigenständigen Code generieren
class SelfContainedUserClient:
"""Vollständig eigenständiger Client ohne Laufzeitabhängigkeiten."""
def __init__(self, base_url: str, api_key: Optional[str] = None):
self._base_url = base_url.rstrip('/')
self._api_key = api_key
def get_user(self, user_id: str) -> dict:
import urllib.request
import urllib.error
url = f'{self._base_url}/users/{user_id}'
req = urllib.request.Request(url, headers=self._headers())
try:
with urllib.request.urlopen(req) as response:
return json.loads(response.read().decode())
except urllib.error.HTTPError as e:
raise APIError(e.code, e.read().decode())
def _headers(self) -> dict:
headers = {'Content-Type': 'application/json'}
if self._api_key:
headers['Authorization'] = f'Bearer {self._api_key}'
return headers
// Korrigiert: Generierte Serialisierung mit Standardbibliotheks-Fallback
// <auto-generated>
// Generiert von ImprovedSerializerGenerator v4.0
// Laufzeit: Optional (verwendet System.Text.Json als Fallback)
// </auto-generated>
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
public partial class GeneratedUserDTO
{
// Korrigiert: Standardbibliotheks-Attribute funktionieren ohne benutzerdefinierte Laufzeit
[JsonPropertyName("id")]
public long Id { get; set; }
[JsonPropertyName("username")]
public string Username { get; set; }
[JsonPropertyName("email")]
public string Email { get; set; }
[JsonPropertyName("created_at")]
public DateTime CreatedAt { get; set; }
// Korrigiert: Eigenständige Serialisierung mit Standardbibliothek
private static readonly JsonSerializerOptions DefaultOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = false,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
public string Serialize()
{
return JsonSerializer.Serialize(this, DefaultOptions);
}
public static GeneratedUserDTO Deserialize(string json)
{
return JsonSerializer.Deserialize<GeneratedUserDTO>(json, DefaultOptions);
}
// Korrigiert: Validierung ist eigenständig
public ValidationResult Validate()
{
var errors = new List<string>();
if (string.IsNullOrEmpty(Username))
errors.Add("Username ist erforderlich");
else if (Username.Length < 3 || Username.Length > 50)
errors.Add("Username muss zwischen 3 und 50 Zeichen haben");
if (string.IsNullOrEmpty(Email))
errors.Add("Email ist erforderlich");
else if (!IsValidEmail(Email))
errors.Add("Ungültiges Email-Format");
return new ValidationResult(errors.Count == 0, errors);
}
private static bool IsValidEmail(string email)
{
// Einfache Email-Validierung ohne Laufzeitabhängigkeit
var atIndex = email.IndexOf('@');
if (atIndex < 1) return false;
var dotIndex = email.LastIndexOf('.');
return dotIndex > atIndex + 1 && dotIndex < email.Length - 1;
}
}
public record ValidationResult(bool IsValid, IReadOnlyList<string> Errors);
CVE-Beispiele
Diese CWE ist für direkte CVE-Zuordnung als VERBOTEN markiert, da sie ein Codequalitätsproblem und keine direkte Sicherheitsschwachstelle darstellt.
Verwandte CWEs
- CWE-710: Improper Adherence to Coding Standards (Eltern)
- CWE-1006: Bad Coding Practices (Kategoriemitglied)
- CWE-1104: Use of Unmaintained Third Party Components (verwandt)
Referenzen
- MITRE Corporation. "CWE-1101: Reliance on Runtime Component in Generated Code." https://cwe.mitre.org/data/definitions/1101.html
- Code Generation Best Practices.
- Dependency Management Guidelines.