CentralCSP
PolitiquesContent-Security-PolicyDirectives

script-src

La directive CSP script-src contrôle quels scripts une page peut charger et exécuter. Valeurs, chaîne de repli, exemples et contournements.

Dernière mise à jour:

La directive script-src d'une politique de sécurité du contenu (Content Security Policy, CSP) décide quels scripts une page est autorisée à charger et à exécuter. Elle régit les éléments <script>, les scripts inline et les event handlers, les URL javascript:, eval() et les évaluations dynamiques similaires, ainsi que les scripts exécutés par les workers. Si un script ne correspond pas à script-src, le navigateur refuse de l'exécuter. C'est la directive la plus importante pour arrêter le cross-site scripting (XSS).

script-src chapeaute deux directives plus fines : script-src-elem pour les éléments <script> et script-src-attr pour les attributs event handler inline. Dès que vous les définissez, chacune prend sa part du travail et script-src devient leur repli.

Une politique minimale sûre pour cette directive :

Content-Security-Policy: script-src 'nonce-{RANDOM}' 'strict-dynamic'

Chaîne de repli

script-src se replie sur default-src. Si vous définissez default-src et omettez script-src, les scripts sont vérifiés contre default-src. Si vous définissez script-src, elle remplace entièrement default-src pour les scripts.

Les directives plus fines se replient sur script-src :

  • script-src-elem se replie sur script-src, puis sur default-src.
  • script-src-attr se replie sur script-src, puis sur default-src.

Un seul script-src couvre donc à la fois les éléments <script> et les handlers inline, sauf si vous surchargez l'un des deux.

Valeurs

script-src accepte une liste de sources séparées par des espaces, ou 'none' pour bloquer tous les scripts.

ValeurStatutDescription
'none'✅ BonBloque tous les scripts. S'utilise seule.
'self'✅ BonScripts de votre propre origine uniquement.
Host source✅ BonUn host précis comme https://cdn.example.com.
https:❌ RisquéN'importe quelle origine HTTPS peut servir du script, autant dire aucun filtrage.
data:❌ RisquéDes URL data: contrôlées par un attaquant s'exécutent comme script.
blob:❌ RisquéLes URL blob: s'exécutent comme script, un vecteur XSS.
'nonce-...'✅ BonJeton aléatoire par réponse, unique et impossible à deviner.
'sha256-...'✅ BonEmpreinte d'un bloc inline exact ou d'un fichier externe.
'strict-dynamic'✅ BonLa confiance découle des scripts autorisés par nonce ou hash ; les sources host et scheme sont ignorées.
'wasm-unsafe-eval'✅ BonCompilation WebAssembly uniquement, plus étroit que 'unsafe-eval'.
'report-sample'✅ BonAjoute les 40 premiers caractères du code inline bloqué aux reports.
'trusted-types-eval'✅ BonN'autorise eval qu'avec TrustedScript quand les Trusted Types sont appliqués. Disponible depuis peu dans les versions actuelles de Chrome, Firefox et Safari.
'unsafe-inline'❌ RisquéAutorise tous les scripts inline, y compris injectés.
'unsafe-eval'❌ RisquéAutorise eval(), new Function() et les timers à base de chaînes.
'unsafe-hashes'❌ RisquéPermet aux hashes de correspondre aux event handlers inline, rouvrant cette surface.
'inline-speculation-rules'🧪 ExpérimentalScripts inline de speculation rules. Porté par Chromium, hors piste de standardisation.
'report-sha256' / 'report-sha384' / 'report-sha512'🧪 ExpérimentalCollecte de hashes en report-only. Chromium uniquement.

Elle accepte :

  • Les sources mots-clés : 'self', 'none', 'unsafe-inline', 'unsafe-eval', 'wasm-unsafe-eval', 'strict-dynamic', 'unsafe-hashes', 'report-sample', 'trusted-types-eval' et 'inline-speculation-rules'.
  • Un nonce ou un hash ('nonce-...', 'sha256-...') pour autoriser des scripts inline ou externes précis.
  • Une host source comme https://cdn.example.com.
  • Une scheme source comme https:.

Deux interactions sont à connaître d'emblée. Ajouter un nonce ou un hash fait ignorer 'unsafe-inline', si bien que les navigateurs plus anciens, qui ne comprennent pas les nonces, gardent quand même la restriction sur l'inline. Ajouter 'strict-dynamic' fait ignorer les entrées host et scheme de la liste : la confiance vient alors d'un nonce ou d'un hash.

Exemples

Une politique à base de nonce qui autorise les scripts de même origine et un script inline portant le nonce correspondant :

Content-Security-Policy: script-src 'self' 'nonce-r4nd0m'

Usage courant

La plupart des pages commencent par autoriser leur propre origine et un petit ensemble de hosts de confiance :

Content-Security-Policy:
    script-src 'self' https://cdn.example.com;
    object-src 'none';
    base-uri 'none'

La recommandation actuelle est une CSP stricte fondée sur un nonce ou un hash plus 'strict-dynamic', plutôt que sur une liste de hosts autorisés. Une liste de hosts se contourne facilement par une redirection ouverte ou un endpoint JSONP sur un domaine autorisé, alors qu'une politique à base de nonce ne fait confiance qu'aux scripts que vous marquez explicitement. Voir le guide sur strict-dynamic et le guide de mise en place des nonces.

Notes de sécurité

script-src est le contrôle central contre le XSS. Un <script> injecté ou un handler inline ne s'exécute que s'il correspond à la directive : un script-src serré transforme donc une injection en violation bloquée et rapportée, au lieu d'une exécution de code.

  • 'unsafe-inline' annule l'essentiel de la protection : il autorise tout script inline, y compris injecté. Retirez-le et passez à un nonce ou un hash. Voir pourquoi abandonner unsafe-inline.
  • 'unsafe-eval' autorise eval(), new Function() et setTimeout avec une chaîne. Évitez-le dès que possible ; beaucoup de bibliothèques n'en ont plus besoin.
  • 'wasm-unsafe-eval' est l'alternative étroite qui n'autorise que la compilation WebAssembly, sans réactiver eval() de manière générale.

L'évaluateur CSP valide une politique en quelques secondes et signale les valeurs faibles de script-src avant leur déploiement.

Contournements et risques connus

La liste de hosts autorisés est le point faible classique. Si une origine autorisée héberge un callback JSONP, une redirection ouverte ou une copie d'un framework permissif, un attaquant peut charger du script par son intermédiaire. 'strict-dynamic' règle le problème en ignorant la liste et en ne faisant confiance qu'aux scripts autorisés par nonce ou hash, et à ce qu'ils créent.

'unsafe-hashes' élargit la correspondance des hashes aux event handlers inline. C'est parfois nécessaire pour du balisage hérité, mais cela relâche la politique ; mieux vaut déplacer les handlers dans des fichiers de script marqués d'un nonce. Un joker comme * ou un scheme large comme https: autorise du script depuis presque n'importe où et revient à ne quasiment pas avoir de script-src.

Recommandation

Pour script-src, déployez une politique stricte à base de nonce plutôt qu'une liste de hosts autorisés, au sein d'une politique de base complète qui définit aussi les autres directives importantes :

Content-Security-Policy:
    default-src 'self';
    script-src 'nonce-{RANDOM}' 'strict-dynamic';
    style-src 'self';
    img-src 'self';
    font-src 'self';
    connect-src 'self';
    media-src 'self';
    manifest-src 'self';
    frame-src 'none';
    worker-src 'self';
    object-src 'none';
    base-uri 'none';
    form-action 'self';
    frame-ancestors 'none';
    upgrade-insecure-requests;
    report-to csp-endpoint

Associez-la à la déclaration d'endpoint, dans un bloc séparé :

Reporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"

C'est la CSP stricte que recommandent la cheat sheet CSP d'OWASP et web.dev, étendue à chaque directive sans repli pour ne rien laisser implicite. 'strict-dynamic' prive d'effet les sources host et scheme : la confiance vient du seul nonce propre à chaque réponse, et se propage aux scripts que votre code autorisé charge. Régénérez le nonce à chaque réponse et laissez 'unsafe-inline' et 'unsafe-eval' hors de la politique.

Reporting

Quand un script est bloqué, le navigateur envoie un report csp-violation nommant script-src (ou la directive résolue script-src-elem / script-src-attr) comme directive effective. Ajoutez 'report-sample' pour inclure un court extrait du code bloqué dans le report, de quoi identifier le script fautif. Pointez votre politique vers un endpoint pour les collecter :

Content-Security-Policy:
    script-src 'self' 'nonce-r4nd0m';
    report-to csp-endpoint

CentralCSP agrège ces reports et construit un inventaire de scripts de tout ce qui s'exécute sur vos pages, ce qui vous montre l'usage réel de script-src avant de resserrer la directive.

Prise en charge par les navigateurs

script-src et ses mots-clés principaux, dont 'strict-dynamic', 'unsafe-eval' et 'unsafe-inline', sont largement pris en charge. 'wasm-unsafe-eval' est largement pris en charge dans les navigateurs actuels. 'trusted-types-eval' est disponible depuis peu dans les versions actuelles de Chrome, Firefox et Safari. 'inline-speculation-rules' est porté par Chromium, disponible dans Safari uniquement derrière un flag, et hors piste de standardisation. La famille 'report-sha256' est propre à Chromium.

FAQ

Faut-il utiliser un nonce ou un hash dans script-src ?

Utilisez un nonce pour les pages rendues côté serveur dont les scripts inline changent à chaque réponse : le serveur tire un nouveau jeton aléatoire à chaque réponse et en marque chaque script de confiance. Utilisez un hash pour les scripts inline statiques qui ne bougent jamais. L'un comme l'autre annulent 'unsafe-inline', si bien que les navigateurs plus anciens gardent la restriction sur l'inline.

Que fait strict-dynamic ?

'strict-dynamic' propage la confiance d'un script déjà autorisé par un nonce ou un hash à tous les scripts que celui-ci crée, si bien qu'un loader de confiance peut charger ses dépendances. En contrepartie, les entrées host et scheme de la liste sont ignorées, ce qui supprime les contournements par redirection ouverte et par JSONP propres aux listes de hosts.

script-src arrête-t-il tout le XSS ?

Non. script-src est le contrôle central qui transforme un script injecté en violation bloquée et rapportée au lieu d'une exécution de code, mais il ne suffit pas à lui seul. Associez-le à object-src 'none' et base-uri 'none' pour fermer les vecteurs des plugins et de la balise base, et ajoutez les Trusted Types pour verrouiller les sinks du DOM.

Voir aussi

Sources

On this page