Skills/web-appsec-hardening/SKILL.md

5.4 KiB

name description
web-appsec-hardening 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

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.
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-.