Le nonce CSP dans Forge¶
Ce document décrit le nonce de Content-Security-Policy par requête.
Il explique comment autoriser un script inline contrôlé sans affaiblir la CSP.
1. Rôle¶
La CSP de Forge interdit les scripts inline par défaut (script-src 'self').
Pour autoriser un script inline contrôlé sans ouvrir globalement la CSP avec unsafe-inline, le module core.security.csp fournit un nonce unique par requête.
Le nonce est stocké en thread-local pour la durée d'une requête, puis remis à zéro.
Le module construit aussi l'en-tête Content-Security-Policy complet.
2. Vue d'ensemble rapide¶
| Élément | Valeur |
|---|---|
| Module | core.security.csp |
| Module Python | core.security.csp |
| Couche | Sécurité |
| Rôle | fournir un nonce CSP par requête et bâtir l'en-tête CSP |
| Dépend de | secrets, threading, contextlib |
| API publique | generate_nonce, set_request_nonce, get_request_nonce, clear_request_nonce, request_nonce, build_csp_header |
| Configuration | variable d'environnement APP_CSP_NONCE_ENABLED |
| Stockage | thread-local (threading.local) |
Quand APP_CSP_NONCE_ENABLED=false (défaut), aucun nonce n'est posé et la CSP reste script-src 'self' seul.
unsafe-inline n'est jamais ajouté automatiquement.
3. Schémas UML¶
3.1 Diagramme de séquence¶
Le diagramme montre la pose d'un nonce le temps d'une requête avec le gestionnaire de contexte request_nonce.
sequenceDiagram
participant Forge as Application Forge
participant CSP as core.security.csp
participant Local as Stockage thread-local
participant Template as Gabarit Jinja
participant Response as Response
Forge->>CSP: generate_nonce()
CSP-->>Forge: nonce
Forge->>CSP: with request_nonce(nonce)
CSP->>Local: set_request_nonce(nonce)
Forge->>CSP: build_csp_header(nonce)
CSP-->>Response: script-src 'self' 'nonce-...'
Template->>CSP: csp_nonce() lit get_request_nonce()
CSP-->>Template: nonce
Forge->>CSP: fin du bloc with
CSP->>Local: clear_request_nonce()
À retenir :
request_nonceest la façon officielle de poser un nonce par requête ;- le bloc
withgarantit la remise à zéro en fin de requête, même en cas d'erreur ; - sans remise à zéro, un nonce pourrait fuiter dans la CSP d'une requête suivante (les threads sont réutilisés) ;
build_csp_header(None)produit une CSP sans nonce.
4. API publique¶
| Fonction | Signature | Rôle |
|---|---|---|
generate_nonce |
generate_nonce() -> str |
génère un nonce sûr (base64 URL-safe, 128 bits) |
set_request_nonce |
set_request_nonce(nonce: str \| None) -> None |
stocke le nonce de la requête courante en thread-local |
get_request_nonce |
get_request_nonce() -> str \| None |
retourne le nonce courant, ou None |
clear_request_nonce |
clear_request_nonce() -> None |
réinitialise le nonce courant |
request_nonce |
request_nonce(nonce: str \| None) -> Generator[str \| None, None, None] |
gestionnaire de contexte qui porte le nonce puis garantit sa remise à zéro |
build_csp_header |
build_csp_header(nonce: str \| None = None) -> str |
construit l'en-tête Content-Security-Policy (avec ou sans nonce) |
5. Contextes d'utilisation¶
| Besoin | Élément |
|---|---|
| Autoriser un script inline contrôlé | activer APP_CSP_NONCE_ENABLED puis poser csp_nonce() sur la balise |
| Poser un nonce le temps d'une requête | with request_nonce(generate_nonce()) |
| Construire l'en-tête CSP | build_csp_header(nonce) |
| Lire le nonce courant dans un gabarit | csp_nonce() (qui s'appuie sur get_request_nonce) |
6. Exemples d'utilisation¶
Pose du nonce et construction de l'en-tête côté serveur :
from core.security.csp import generate_nonce, request_nonce, build_csp_header
with request_nonce(generate_nonce()) as nonce:
response.headers["Content-Security-Policy"] = build_csp_header(nonce)
# rendu du template : csp_nonce() retourne nonce
Dans un gabarit Jinja :
7. Sécurité¶
Jamais unsafe-inline
build_csp_header n'ajoute jamais unsafe-inline.
Seul un nonce valide autorise un script inline ; sinon la CSP reste script-src 'self'.
Stockage thread-local
Le nonce vit dans un stockage thread-local et les threads sont réutilisés par le serveur de développement.
Utiliser request_nonce plutôt que set_request_nonce directement garantit la remise à zéro en fin de requête.
Voir aussi¶
- Les en-têtes de sécurité dans Forge : la CSP fait partie du socle d'en-têtes posés.