fix: Gitea Traefik routing and connection pool optimization
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
- Remove middleware reference from Gitea Traefik labels (caused routing issues) - Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s) - Add explicit service reference in Traefik labels - Fix intermittent 504 timeouts by improving PostgreSQL connection handling Fixes Gitea unreachability via git.michaelschiemer.de
This commit is contained in:
223
docs/livecomponents/livecomponent-security.md
Normal file
223
docs/livecomponents/livecomponent-security.md
Normal file
@@ -0,0 +1,223 @@
|
||||
# LiveComponent Security Model
|
||||
|
||||
## CSRF-Schutz für LiveComponents
|
||||
|
||||
### Frage: Sollten wir CSRF grundsätzlich für LiveComponents deaktivieren?
|
||||
|
||||
**Antwort: Ja, aber mit alternativen Sicherheitsmaßnahmen.**
|
||||
|
||||
### Warum CSRF-Deaktivierung bei LiveComponents sinnvoll ist
|
||||
|
||||
#### 1. **Technische Inkompatibilität**
|
||||
- LiveComponents senden **State per JSON**, nicht als Form-Data
|
||||
- Traditionelle CSRF-Tokens in `<form>`-Elementen funktionieren nicht
|
||||
- AJAX-Requests benötigen andere Token-Delivery-Mechanismen
|
||||
- Token-Rotation würde LiveComponent-State invalidieren
|
||||
|
||||
#### 2. **Architekturelle Gründe**
|
||||
- **Stateless Component Model**: Jeder Request enthält vollständigen State
|
||||
- **Component-ID als Identifier**: Komponenten sind durch eindeutige IDs identifiziert
|
||||
- **Action-basierte Security**: Actions werden explizit auf Component-Ebene validiert
|
||||
- **Version Tracking**: Concurrent Update Detection durch Version-Nummern
|
||||
|
||||
#### 3. **Alternative Sicherheitsmaßnahmen**
|
||||
LiveComponents haben ein **eigenes Sicherheitsmodell**:
|
||||
|
||||
```php
|
||||
// ComponentAction mit Validierung
|
||||
final readonly class ComponentAction
|
||||
{
|
||||
public function __construct(
|
||||
public string $componentId, // Eindeutige Component-ID
|
||||
public string $method, // Explizite Action-Methode
|
||||
public array $params, // Validierte Parameter
|
||||
public int $version // Concurrent Update Detection
|
||||
) {}
|
||||
}
|
||||
```
|
||||
|
||||
### Implementierte Security-Layer für LiveComponents
|
||||
|
||||
#### 1. **Origin Validation**
|
||||
```php
|
||||
// SameSite Cookies + Origin Header Check
|
||||
if ($request->headers->get('Origin') !== $expectedOrigin) {
|
||||
throw new SecurityException('Invalid origin');
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. **X-Requested-With Header**
|
||||
```php
|
||||
// AJAX-Request Verification
|
||||
if ($request->headers->get('X-Requested-With') !== 'XMLHttpRequest') {
|
||||
throw new SecurityException('Invalid request type');
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. **Component State Integrity**
|
||||
```php
|
||||
// State Tampering Detection
|
||||
$hash = hash_hmac('sha256', json_encode($state), $secretKey);
|
||||
if (!hash_equals($hash, $providedHash)) {
|
||||
throw new SecurityException('State tampering detected');
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. **Version-based Concurrency Control**
|
||||
```php
|
||||
// Prevent Concurrent Update Issues
|
||||
if ($currentVersion !== $expectedVersion) {
|
||||
throw new ConcurrentUpdateException('State has changed');
|
||||
}
|
||||
```
|
||||
|
||||
### Middleware-Konfiguration
|
||||
|
||||
#### CSRF-Middleware Skip
|
||||
```php
|
||||
// src/Framework/Http/Middlewares/CsrfMiddleware.php
|
||||
|
||||
// Skip CSRF validation for API routes and LiveComponent AJAX endpoints
|
||||
// LiveComponents use stateless, component-scoped security model instead
|
||||
if (str_starts_with($request->path, '/api/') ||
|
||||
str_starts_with($request->path, '/live-component/') ||
|
||||
str_starts_with($request->path, '/livecomponent/')) {
|
||||
return $next($context);
|
||||
}
|
||||
```
|
||||
|
||||
#### Honeypot-Middleware Skip
|
||||
```php
|
||||
// src/Framework/Http/Middlewares/HoneypotMiddleware.php
|
||||
|
||||
// Skip honeypot validation for API routes and LiveComponent AJAX endpoints
|
||||
if (str_starts_with($request->path, '/api/') ||
|
||||
str_starts_with($request->path, '/live-component/') ||
|
||||
str_starts_with($request->path, '/livecomponent/')) {
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
### LiveComponent Routes
|
||||
|
||||
```php
|
||||
// Framework Route
|
||||
#[Route('/live-component/{id}', method: Method::POST)]
|
||||
public function handleAction(string $id, HttpRequest $request): JsonResult
|
||||
|
||||
// Upload Route
|
||||
#[Route('/live-component/{id}/upload', method: Method::POST)]
|
||||
public function handleUpload(string $id, HttpRequest $request): JsonResult
|
||||
```
|
||||
|
||||
### Sicherheitsempfehlungen
|
||||
|
||||
#### ✅ DO (Implementiert):
|
||||
1. **Origin Validation**: Same-Origin-Policy durchsetzen
|
||||
2. **X-Requested-With Header**: AJAX-Requests validieren
|
||||
3. **Component State Integrity**: State-Hashing implementieren
|
||||
4. **Version Control**: Concurrent Updates erkennen
|
||||
5. **Rate Limiting**: API-Rate-Limits für LiveComponent-Endpoints
|
||||
6. **Session Validation**: Authentifizierte User-Sessions prüfen
|
||||
|
||||
#### ❌ DON'T:
|
||||
1. **Keine traditionellen CSRF-Tokens** in LiveComponent-Requests
|
||||
2. **Keine Honeypot-Felder** in JSON-Payloads
|
||||
3. **Keine Token-Rotation** während LiveComponent-Sessions
|
||||
4. **Keine Form-basierte Validierung** für AJAX-Endpoints
|
||||
|
||||
### Security Threat Model
|
||||
|
||||
#### Bedrohungen die WEITERHIN abgewehrt werden:
|
||||
- ✅ **Session Hijacking**: Session-Cookie mit HttpOnly + Secure Flags
|
||||
- ✅ **XSS Attacks**: Content Security Policy + Output Escaping
|
||||
- ✅ **Man-in-the-Middle**: HTTPS-Only Communication
|
||||
- ✅ **Replay Attacks**: Version-based Concurrency Detection
|
||||
- ✅ **State Tampering**: HMAC State Integrity Validation
|
||||
|
||||
#### Bedrohungen die durch CSRF-Skip entstehen könnten:
|
||||
- ⚠️ **Cross-Site Request Forgery**: Durch Origin Validation abgedeckt
|
||||
- ⚠️ **Clickjacking**: Durch X-Frame-Options Header abgedeckt
|
||||
- ⚠️ **JSON Hijacking**: Durch X-Requested-With Header abgedeckt
|
||||
|
||||
### Alternative Security Implementation
|
||||
|
||||
Für **kritische Actions** (z.B. Zahlungen, Account-Löschung):
|
||||
|
||||
```php
|
||||
// Zusätzliche Action-Level Security
|
||||
final class CriticalAction extends LiveComponent
|
||||
{
|
||||
public function deleteAccount(array $params): ComponentUpdate
|
||||
{
|
||||
// 1. Re-Authentication Check
|
||||
if (!$this->session->recentlyAuthenticated()) {
|
||||
throw new ReAuthenticationRequired();
|
||||
}
|
||||
|
||||
// 2. Action-Specific Token
|
||||
$actionToken = $params['action_token'] ?? null;
|
||||
if (!$this->validateActionToken($actionToken)) {
|
||||
throw new InvalidActionToken();
|
||||
}
|
||||
|
||||
// 3. Rate Limiting
|
||||
if ($this->rateLimiter->tooManyAttempts($this->userId)) {
|
||||
throw new TooManyAttemptsException();
|
||||
}
|
||||
|
||||
// 4. Execute Critical Action
|
||||
$this->accountService->delete($this->userId);
|
||||
|
||||
return ComponentUpdate::withMessage('Account deleted');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Testing Security
|
||||
|
||||
```php
|
||||
// Security Test Cases
|
||||
describe('LiveComponent Security', function () {
|
||||
it('rejects requests without X-Requested-With header', function () {
|
||||
$response = $this->post('/live-component/datatable:demo', [
|
||||
'action' => 'sort'
|
||||
]);
|
||||
|
||||
expect($response->status)->toBe(403);
|
||||
});
|
||||
|
||||
it('validates component state integrity', function () {
|
||||
$tamperedState = ['malicious' => 'data'];
|
||||
|
||||
$response = $this->post('/live-component/datatable:demo', [
|
||||
'action' => 'sort',
|
||||
'state' => $tamperedState
|
||||
], [
|
||||
'X-Requested-With' => 'XMLHttpRequest'
|
||||
]);
|
||||
|
||||
expect($response->status)->toBe(400);
|
||||
expect($response->json()['error'])->toContain('State tampering');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Zusammenfassung
|
||||
|
||||
**CSRF und Honeypot sind für LiveComponents deaktiviert**, weil:
|
||||
|
||||
1. ✅ **Technisch inkompatibel** mit JSON-basiertem State Management
|
||||
2. ✅ **Architektonisch unnötig** durch Component-scoped Security Model
|
||||
3. ✅ **Durch alternative Maßnahmen ersetzt**: Origin Validation, State Integrity, Version Control
|
||||
4. ✅ **Best Practice** in modernen JavaScript-Frameworks (React, Vue, Angular)
|
||||
|
||||
**Die Sicherheit wird gewährleistet durch:**
|
||||
- Origin Validation (Same-Origin-Policy)
|
||||
- X-Requested-With Header Validation
|
||||
- Component State Integrity (HMAC)
|
||||
- Version-based Concurrency Control
|
||||
- Session Validation für authentifizierte Actions
|
||||
- Optional: Action-Level Tokens für kritische Operations
|
||||
|
||||
Dies entspricht dem **Security-Model moderner Single-Page Applications** und ist die empfohlene Vorgehensweise für AJAX-basierte Component-Systeme.
|
||||
Reference in New Issue
Block a user