security: appliquer les findings de l'audit OWASP (H1→B3)
H1 — trusted_proxies RFC-1918 dans framework.yaml : rate limiting
opérationnel derrière Traefik (IP client réelle, pas IP Traefik)
H2 — En-têtes HTTP dans Caddyfile : X-Frame-Options DENY,
X-Content-Type-Options nosniff, Referrer-Policy, Permissions-Policy,
suppression header Server
H3 — API Platform docs désactivés en when@prod (Swagger UI, ReDoc)
M1 — Rate limiter sur DELETE /api/push/subscribe (manquant)
M2 — Validation FILTER_VALIDATE_URL sur endpoint push avant stockage
M3 — APP_ENV=prod dans backend/.env (était dev — risque si .env.local absent)
M4 — Limite 4096 octets sur le body JSON (FeedbackController + PushController)
M5 — Service Worker : open redirect corrigé (targetUrl validé contre l'origine)
B1 — robots.txt créé (bloque /api/ et /bundles/)
B3 — --time-limit=3600 sur les workers Messenger (rotation + libération mémoire)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,10 @@ class FeedbackController extends AbstractController
|
||||
return $this->json(['error' => 'Too many requests'], 429);
|
||||
}
|
||||
|
||||
if (strlen($request->getContent()) > 4096) {
|
||||
return $this->json(['error' => 'Request body too large'], 413);
|
||||
}
|
||||
|
||||
$data = json_decode($request->getContent(), true);
|
||||
|
||||
if (!is_array($data)) {
|
||||
|
||||
@@ -49,12 +49,20 @@ class PushController extends AbstractController
|
||||
return $this->json(['error' => 'Too many requests'], 429);
|
||||
}
|
||||
|
||||
if (strlen($request->getContent()) > 4096) {
|
||||
return $this->json(['error' => 'Request body too large'], 413);
|
||||
}
|
||||
|
||||
$data = json_decode($request->getContent(), true);
|
||||
|
||||
if (!isset($data['endpoint'], $data['keys']['auth'], $data['keys']['p256dh'])) {
|
||||
return $this->json(['error' => 'Missing required fields'], 422);
|
||||
}
|
||||
|
||||
if (!filter_var($data['endpoint'], FILTER_VALIDATE_URL)) {
|
||||
return $this->json(['error' => 'Invalid endpoint URL'], 422);
|
||||
}
|
||||
|
||||
// Upsert : si l'endpoint existe déjà, on met à jour
|
||||
$repo = $this->em->getRepository(PushSubscription::class);
|
||||
$sub = $repo->findOneBy(['endpoint' => $data['endpoint']]) ?? new PushSubscription();
|
||||
@@ -81,6 +89,11 @@ class PushController extends AbstractController
|
||||
#[Route('/subscribe', name: 'unsubscribe', methods: ['DELETE'])]
|
||||
public function unsubscribe(Request $request): JsonResponse
|
||||
{
|
||||
$limiter = $this->apiPushLimiter->create($request->getClientIp() ?? 'unknown');
|
||||
if (!$limiter->consume()->isAccepted()) {
|
||||
return $this->json(['error' => 'Too many requests'], 429);
|
||||
}
|
||||
|
||||
$data = json_decode($request->getContent(), true);
|
||||
if (empty($data['endpoint'])) {
|
||||
return $this->json(['error' => 'Missing endpoint'], 422);
|
||||
|
||||
Reference in New Issue
Block a user