Skills/web-appsec-hardening/SKILL.md

102 lines
5.4 KiB
Markdown

---
name: web-appsec-hardening
description: >-
Enforce modern web application security (AppSec) standards on frontend and edge layers.
Implements Strict CSP Level 3 (nonce + strict-dynamic), OWASP Secure Headers, DOM sanitization,
secure cookie attributes, CSRF mitigation, and subresource integrity (SRI).
---
# Web AppSec & Frontend Hardening
Ce skill impose les standards actuels de sécurité applicative (W3C CSP Level 3, OWASP Secure Headers, DOMPurify, RFC 6265bis) sur la couche front-end et edge des applications web modernes.
---
## 🎯 Déclencheurs d'Activation
Activez ce skill dès que :
1. Vous configurez un middleware de sécurité, un serveur HTTP ou des en-têtes de réponse (Next.js, Remix, Astro, Express, Fastify, Nginx).
2. Vous intégrez des scripts tiers (analytics, trackers, widgets, balises).
3. Vous affichez du contenu dynamique ou du HTML généré par l'utilisateur (Markdown, éditeur WYSIWYG, commentaires).
4. Vous configurez des cookies de session ou des jetons d'authentification.
5. Vous auditez la sécurité d'une interface web avant mise en production.
---
## 🛡️ 1. Content Security Policy (Strict CSP Level 3)
### La Règle d'Or : Abandon des Allowlists au profit du Nonce + `strict-dynamic`
Les listes blanches de domaines (`script-src https://cdnjs.cloudflare.com ...`) sont fragiles, obsolètes et contournables. La norme moderne repose sur un **nonce cryptographique unique par requête**.
### Structure de l'en-tête Strict CSP
```http
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-RANDOM_VALUE' 'strict-dynamic'; style-src 'self' 'unsafe-inline'; img-src 'self' blob: data: https:; font-src 'self'; object-src 'none'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests;
```
### Mécanisme :
- `'nonce-RANDOM_VALUE'` : Généré côté serveur (UUID cryptographique base64) à chaque requête HTTP et injecté dans la balise `<script nonce="...">`.
- `'strict-dynamic'` : Autorise les scripts signés par le nonce à charger dynamiquement d'autres scripts enfants sans devoir ajouter chaque domaine tiers dans le CSP.
- `object-src 'none'` : Désactive les plugins obsolètes (Flash, Java).
- `base-uri 'none'` : Empêche le détournement de l'élément `<base>`.
- `frame-ancestors 'none'` : Prévient le Clickjacking en interdisant l'encapsulation dans une iframe.
---
## 🔒 2. En-têtes de Sécurité Obligatoires (OWASP Top)
Tout serveur ou middleware doit émettre systématiquement :
| En-tête HTTP | Valeur Standard Recommandée | Rôle |
| :--- | :--- | :--- |
| **Strict-Transport-Security** | `max-age=63072000; includeSubDomains; preload` | Force HTTPS pendant 2 ans et éligibilité à la liste HSTS preload. |
| **X-Content-Type-Options** | `nosniff` | Empêche le navigateur d'exécuter du code déguisé en type MIME alternatif (MIME sniffing). |
| **Referrer-Policy** | `strict-origin-when-cross-origin` | Protège les paramètres d'URL sensibles lors de redirections externes. |
| **Permissions-Policy** | `camera=(), microphone=(), geolocation=(), payment=()` | Bloque l'accès aux API matérielles non autorisées pour la page et ses iframes. |
| **X-Frame-Options** | `DENY` | Mesure de compatibilité avec les anciens navigateurs ne gérant pas `frame-ancestors`. |
---
## 🧼 3. Sanitisation du DOM & Prévention XSS
- **Interdiction Formelle** : Ne jamais utiliser `dangerouslySetInnerHTML` ou `element.innerHTML` avec des données non assainies.
- **Bibliothèque de Référence** : Utiliser **DOMPurify** (`isomorphic-dompurify` pour SSR / Node).
- **Images SVG** : Les SVG injectés inline doivent être expurgés de toute balise `<script>`, `<foreignObject>` et des gestionnaires d'événements `onload`, `onerror`.
```typescript
import DOMPurify from 'isomorphic-dompurify';
export const SafeHTML = ({ htmlContent }: { htmlContent: string }) => {
const sanitized = DOMPurify.sanitize(htmlContent, {
USE_PROFILES: { html: true },
FORBID_TAGS: ['style', 'script', 'iframe', 'object'],
FORBID_ATTR: ['onerror', 'onload', 'onclick'],
});
return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;
};
```
---
## 🍪 4. Sécurité des Cookies & Jetons (RFC 6265bis)
Tout cookie d'authentification ou de session doit comporter les drapeaux stricts :
- **`HttpOnly`** : Inaccessible via `document.cookie` (bloque l'exfiltration via XSS).
- **`Secure`** : Transmis uniquement sur connexion chiffrée TLS.
- **`SameSite=Strict`** (ou `Lax` pour les flux OAuth externes) : Bloque les requêtes cross-site non sollicitées (anti-CSRF).
- **Préfixes Sécurisés** :
- `__Host-session_id` : Impose que le cookie provienne du même hôte (pas de sous-domaine), avec `Secure` et chemin `/`.
- `__Secure-token` : Impose le flag `Secure`.
---
## 📋 Checklist de Conformité AppSec (Pre-Production)
- [ ] Un `nonce` unique est généré pour chaque requête et injecté dans les scripts racine.
- [ ] Le header `Content-Security-Policy` avec `strict-dynamic` est actif et sans avertissements console.
- [ ] `Strict-Transport-Security` avec `max-age=63072000; includeSubDomains; preload` est présent.
- [ ] `X-Content-Type-Options: nosniff` est actif.
- [ ] `Permissions-Policy` désactive les API matérielles inutilisées.
- [ ] Tout HTML utilisateur passe par `DOMPurify`.
- [ ] Les cookies d'authentification utilisent `HttpOnly`, `Secure`, `SameSite=Strict` et le préfixe `__Host-`.