102 lines
5.4 KiB
Markdown
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-`.
|