# no-cache vs no-store, quelle directive Cache-Control garde les données privées (/fr/blog/no-cache-vs-no-store)



Les noms sonnent comme des synonymes, et c'est le piège. `no-cache` ne veut pas dire
« ne pas mettre en cache ». Il veut dire « stocke-le, mais vérifie auprès du serveur
avant de le réutiliser ». La directive qui garde réellement une réponse hors des
caches est `no-store`, et, pour une page qui contient des données personnelles, cette
différence change tout.

Pour une réponse qui transporte un identifiant de session ou des données
personnelles, la directive [`Cache-Control`](/fr/docs/web-security/security-headers/cache-control)
à utiliser est `no-store`. `no-cache` laisse le navigateur et les caches
partagés conserver les octets ; il force seulement une revalidation avant réutilisation.
Pour la confidentialité, stocké-mais-revalidé ne suffit pas ; vous voulez jamais-stocké.

## no-cache vs no-store, ce que chaque directive dit à un cache [#no-cache-vs-no-store-ce-que-chaque-directive-dit-à-un-cache]

Les deux directives viennent du [RFC 9111](https://httpwg.org/specs/rfc9111.html), la
spécification de la mise en cache HTTP, qui les définit précisément. La confusion tient
entièrement aux noms, alors commençons par ce que chacune demande vraiment à un
cache.

Deux niveaux de cache sont à garder en tête. Un cache privé est le navigateur de
l'utilisateur. Un cache partagé est un proxy d'entreprise, un CDN, ou un reverse proxy
qui stocke une réponse et la réutilise pour de nombreux utilisateurs. HTTP est conçu
pour mettre en cache de façon agressive, si bien qu'une réponse sans aucun header
`Cache-Control` peut quand même être stockée et réutilisée via la mise en cache
heuristique (RFC 9111 section 4.2.2, avec une durée de vie heuristique typiquement
autour de 10 % de l'ancienneté `Last-Modified` de la ressource). La spécification
est d'ailleurs explicite sur le fait que `Set-Cookie` n'empêche pas la mise en cache : une réponse
cachable portant un header `Set-Cookie` peut servir, et sert souvent, à
satisfaire d'autres requêtes. Si vous voulez qu'une réponse reste hors des caches,
il faut le dire.

## no-cache stocke la réponse, puis revalide [#no-cache-stocke-la-réponse-puis-revalide]

`no-cache` (RFC 9111 section 5.2.2.4) signifie qu'un cache **peut** stocker la réponse
mais **ne doit pas** la réutiliser sans une revalidation réussie auprès du serveur
d'origine. Le stockage est permis, pas imposé, donc la copie peut se trouver sur le
disque ou en mémoire. À la requête suivante, le cache demande au serveur « ma copie
est-elle encore bonne ? » et ne la réutilise que sur un 304. MDN le dit textuellement :
« no-cache ne veut pas dire ne pas mettre en cache ».

```http
Cache-Control: no-cache
```

Côté confidentialité, cela n'apporte rien. La réponse peut se retrouver dans le cache, et
quiconque y a accès, que ce soit le proxy partagé ou le disque de l'utilisateur sur une
machine partagée, peut lire la copie stockée. La revalidation contrôle la fraîcheur, pas qui
peut voir les octets. Elle ne contraint pas non plus votre edge. Cloudflare respecte le
`Cache-Control` de l'origine par défaut, mais les cache rules et les réglages de TTL
edge peuvent le compléter ou le remplacer, donc `no-cache` à l'origine ne contraint pas
une couche CDN mal configurée.

## no-store garde la réponse hors de tout cache [#no-store-garde-la-réponse-hors-de-tout-cache]

`no-store` (RFC 9111 section 5.2.2.5) est la directive stricte. Un cache « NE DOIT PAS
stocker la moindre partie de la requête immédiate ou de la réponse et NE DOIT PAS
utiliser la réponse pour satisfaire une autre requête ». Cela s'applique aussi bien aux
caches privés qu'aux caches partagés.

```http
Cache-Control: no-store
```

C'est la directive pour toute réponse contenant un identifiant de session ou des
données personnelles, et c'est ce que la cheat sheet Session Management de l'OWASP
prescrit pour les réponses transportant des identifiants de session. Avec `no-store`,
les directives supplémentaires et le header `Expires` que l'on empile par habitude sont
généralement inutiles pour les navigateurs modernes. L'incantation héritée
`private, no-cache, no-store, max-age=0, must-revalidate` est, selon l'exemple même de
MDN, équivalente à un simple `no-store`, parce que la directive la plus restrictive
l'emporte.

Une réserve, venue de la spécification elle-même : le RFC 9111 avertit que `no-store`
« n'est pas un mécanisme fiable ou suffisant pour garantir la confidentialité », parce
que des caches malveillants ou non conformes pourraient ne pas l'honorer. C'est une
instruction adressée aux caches bien élevés, pas du chiffrement. Utilisez-la, mais n'en
faites pas votre seul contrôle.

## private ne stoppe que les caches partagés [#private-ne-stoppe-que-les-caches-partagés]

`private` (RFC 9111 section 5.2.2.7) dit que les caches partagés ne doivent pas stocker
la réponse, mais le cache propre du navigateur le peut encore. Elle réserve à un seul
utilisateur une réponse personnalisée en la gardant hors des proxies et des CDN, ce qui est
utile, mais ce n'est pas un contrôle de confidentialité contre le stockage local des
octets. `private` seule laisse toujours la réponse sur le disque de l'utilisateur.

```http
Cache-Control: private, no-cache
```

Cette combinaison, `private, no-cache`, est un compromis raisonnable pour une page
personnalisée qu'on peut mettre en cache dans le navigateur mais qui doit revalider et
ne jamais toucher un cache partagé. Ce n'est pas le réglage pour un token de session ;
celui-là reste `no-store`.

Se tromper à ce niveau a déjà eu des conséquences. Les attaques de web cache deception
fonctionnent précisément quand un cache partagé peut stocker du contenu dynamique propre
à un utilisateur, et la défense est `no-store` ou `private` sur les réponses dynamiques.
Dans l'incident Steam de Noël 2015, une couche de cache a servi des pages du store
authentifiées aux mauvais utilisateurs : les pages d'environ
34 000 utilisateurs, dont certaines contenaient des adresses de facturation et des
chiffres partiels de carte bancaire, se sont affichées chez d'autres clients.

## no-cache vs no-store vs private, côte à côte [#no-cache-vs-no-store-vs-private-côte-à-côte]

| Directive  | Peut être stockée ?          | Réutilisée sans demander au serveur ? | Quels caches                      |
| ---------- | ---------------------------- | ------------------------------------- | --------------------------------- |
| `no-store` | Non                          | Jamais stockée                        | Privé et partagé                  |
| `no-cache` | Autorisé (disque ou mémoire) | Non, revalide d'abord                 | Privé et partagé                  |
| `private`  | Navigateur seulement         | Oui, tant que fraîche                 | Privé seulement, partagé interdit |

## Le back/forward cache joue selon d'autres règles [#le-backforward-cache-joue-selon-dautres-règles]

Le back/forward cache (bfcache) n'est pas un cache HTTP. Il garde un instantané vivant
d'une page pour qu'un retour arrière soit instantané, et parce qu'il restaure
l'instantané sans revalider, `Cache-Control` ne le gouverne que partiellement. MDN note
que même `no-cache` ne garantit pas la revalidation lors des navigations dans
l'historique.

Chrome restaure désormais même les pages `no-store` depuis le bfcache (le déploiement à
tous les utilisateurs s'est achevé en 2025), avec des atténuations : la page n'est pas
restaurée si elle a utilisé WebSocket, WebTransport ou WebRTC, l'entrée est évincée
quand les cookies ou d'autres méthodes d'autorisation changent ou quand une requête de
sous-ressource revient avec `no-store`, et l'entrée est plafonnée à 3 minutes au lieu
des 10 habituelles. La documentation de Chrome note que d'autres navigateurs peuvent
encore bloquer le bfcache quand `Cache-Control: no-store` est présent, donc ne supposez
pas un comportement uniforme entre les moteurs.

La conséquence de sécurité est concrète : un utilisateur qui se déconnecte et clique sur
le bouton retour peut retomber sur la page authentifiée. La déconnexion
doit donc vraiment invalider la session, en changeant ou en effaçant le
[cookie de session](/fr/docs/web-security/security-headers/cookie-security) côté
serveur, pas se contenter de rediriger ailleurs. Comme l'éviction du bfcache dépend d'un
changement de cookie, c'est l'effacement du cookie de session qui rend la page restaurée
inoffensive, pas la directive de cache. L'OWASP recommande en plus d'effacer l'état client à
la déconnexion avec un header `Clear-Site-Data`.

```http
Clear-Site-Data: "cache", "cookies", "storage"
```

Les directives sont des chaînes entre guillemets et le header ne fonctionne qu'en HTTPS.
La prise en charge de `"cookies"` et `"storage"` est large ; celle de `"cache"` est inégale
selon les moteurs, alors traitez-le comme une couche supplémentaire, pas comme le
mécanisme principal. Pour les navigateurs où une restauration bfcache reste possible, web.dev
suggère une vérification ceinture et bretelles : écouter l'event `pageshow`, vérifier
qu'un cookie propre au site est toujours présent, et forcer un rechargement s'il a
disparu.

L'erreur existe aussi dans l'autre sens. N'utilisez pas `no-store` comme bloqueur de
bfcache sur des pages ordinaires. La recommandation de web.dev est de réserver
`no-store` aux pages où toute mise en cache est inappropriée, et d'utiliser `no-cache`
ou `max-age=0` ailleurs, qui n'affectent pas l'éligibilité d'une page au
bfcache. Un `no-store` généralisé tue la navigation arrière/avant instantanée sans
aucun gain de sécurité.

## Recommandation [#recommandation]

Réglez la mise en cache par réponse, pas à l'échelle du site. Envoyez
`Cache-Control: no-store` sur toute réponse qui transporte un identifiant de session ou
des données sensibles, connexion, compte, paiement, tout ce qui est personnalisé.
Gardez la mise en cache longue durée là où elle a sa place, sur les assets statiques dont
le nom porte une empreinte, avec `max-age=31536000, immutable`.

```http
Cache-Control: max-age=31536000, immutable
```

Une note sur `immutable` : Firefox et Safari l'honorent, Chrome et Edge l'ignorent.
Cet oubli est sans conséquence : le `max-age` s'applique quand même, donc l'approche
reste valable partout.

Et associez `no-store` à une vraie déconnexion : invalidez la session côté serveur,
effacez le cookie de session, et envoyez `Clear-Site-Data` pour qu'une page restaurée du
bfcache ne puisse pas montrer de contenu authentifié. Le
[scanner de headers de sécurité](/tools/security-headers) gratuit de CentralCSP repère les
réponses qui posent ou exigent un cookie de session sans porter la moindre directive les
gardant hors des caches partagés, pour que vous ajoutiez `no-store` avant que cela ne tourne à la fuite.

## FAQ [#faq]

### Pourquoi Cache-Control no-cache ne fonctionne-t-il pas ? [#pourquoi-cache-control-no-cache-ne-fonctionne-t-il-pas-]

Il fonctionne, en général, exactement comme spécifié. `no-cache` permet le stockage et
permet la réutilisation après une revalidation 304, donc des copies en cache sur le
disque et des rechargements rapides sont normaux. Les restaurations via le bouton
retour peuvent le contourner entièrement, parce que le bfcache restaure un instantané
sans revalider. Et une couche CDN avec ses propres cache rules peut passer outre les
headers de l'origine. Si le comportement que vous vouliez était « jamais stocké », la
directive que vous vouliez était `no-store`.

### no-cache empêche-t-il la mise en cache ? [#no-cache-empêche-t-il-la-mise-en-cache-]

Non. Il empêche la réutilisation sans revalidation, pas le stockage. MDN le dit
directement : si le sens de « ne pas mettre en cache » que vous voulez est en réalité
« ne pas stocker », alors `no-store` est la directive à utiliser.

### Quelle directive Cache-Control utiliser pour des données sensibles ? [#quelle-directive-cache-control-utiliser-pour-des-données-sensibles-]

`Cache-Control: no-store` sur chaque réponse transportant un identifiant de session ou
des données personnelles. C'est la recommandation de l'OWASP, et les directives
supplémentaires ainsi que le header `Expires` sont généralement inutiles pour les
navigateurs modernes.

### Le bouton retour peut-il afficher une page envoyée avec no-store ? [#le-bouton-retour-peut-il-afficher-une-page-envoyée-avec-no-store-]

Oui, dans Chrome. `no-store` garde la réponse hors des caches HTTP, mais Chrome
restaure même les pages `no-store` depuis le bfcache, avec éviction lors des changements
de cookies et un plafond de 3 minutes. Le bouton retour peut donc encore afficher la
page, sauf si la déconnexion a changé ou effacé le cookie de session. Associez
l'invalidation de session côté serveur à `Clear-Site-Data`, et éventuellement une
vérification de cookie sur `pageshow` qui recharge la page.

### Dois-je utiliser no-store sur toutes les pages ? [#dois-je-utiliser-no-store-sur-toutes-les-pages-]

Non. Réservez `no-store` aux réponses où toute mise en cache est inappropriée, tout ce
qui transporte un identifiant de session ou des données personnelles. Sur une page
ordinaire, il force un téléchargement complet à chaque requête et peut bloquer les
restaurations du back/forward cache dans certains moteurs, donc la navigation devient
plus lente sans aucun gain de sécurité. Utilisez `no-cache` ou `max-age=0` à la place.

## À lire ensuite [#à-lire-ensuite]

* [Comment améliorer votre note de headers de sécurité](/fr/blog/improve-security-headers-grade)
* [SameSite contre les tokens CSRF, qui protège vos sessions](/fr/blog/samesite-vs-csrf-tokens)
* [Référence Cache-Control](/fr/docs/web-security/security-headers/cache-control)
* [Référence cookie security](/fr/docs/web-security/security-headers/cookie-security)

## Sources [#sources]

* [RFC 9111, HTTP Caching](https://httpwg.org/specs/rfc9111.html)
* [MDN, Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control)
* [MDN, guide de la mise en cache HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching)
* [Chrome, bfcache and Cache-Control no-store](https://developer.chrome.com/docs/web-platform/bfcache-ccns)
* [web.dev, Back/forward cache](https://web.dev/articles/bfcache)
* [OWASP, Session Management cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html)
* [OWASP WSTG, Testing for Browser Cache Weaknesses](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/04-Authentication_Testing/06-Testing_for_Browser_Cache_Weaknesses)
* [MDN, Clear-Site-Data](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Clear-Site-Data)
* [PortSwigger, Web cache deception](https://portswigger.net/web-security/web-cache-deception)
* [Cloudflare, Cache-Control at the edge](https://developers.cloudflare.com/cache/concepts/cache-control/)
