Pentesting Fundamentals

Cache Controls Explained

our services

Cache controls have been a fixture on application penetration test reports for over 20 years. They control a balance between security and performance which is still frequently debated today.

On one hand, security standards recommend that no application data is cached or stored in local browser directories. On the other hand, performance improves as artifacts and data can be cached to avoid excessive requests.

Although ultimately a low risk in nearly all contexts, organizations must decide what levels of caching are acceptable for their applications.

Cache Controls and Vulnerability Risk

Let’s first review some scenarios where caching may pose risk:

  1. Sensitive data stored locally is exposed to others in shared workstation environments, or forensically recovered if a device is lost.
  2. A malicious actor gains temporary access to a user’s device. The cached data (even when it’s not sensitive) indicates the owner is a user of your application, and the actor can then further target the owner.

Cache Controls

There are three cache controls relevant to a penetration test: Cache-Control, Expires, and Pragma. These are the core controls to instruct web clients on how data should be cached.

1. Cache-Control

Cache-Control has a number of directives which are frequently misunderstood.

no-cache is the most frequent offender, where despite it’s name, it does not prevent data being cached locally. no-cache only forces validation of the cached content, so the browser may store the data, but must check for new versions when the page is requested again.

private is also frequently misused. The term ‘private’ here is only reserved for “shared caches” such as proxies and does not apply to the end user. private does not prevent any caching by web browsers.

no-store is the strongest and preferred directive for secure applications. no-store instructs browsers not to store the content locally and is the only necessary directive.

2. Pragma

Pragma is a header for HTTP/1.0 clients that do not support HTTP/1.1. Pragma supports only one directive, no-cache.

3. Expires

Expires instructs the client how long to retain the content. Expires is also identical to the max-age directive of the Cache-Control header and is ignored when max-age is used.

Viewing Cached Data

For penetration testers needing a proof of concept for cached data, Chrome and FireFox browsers no longer store cached pages in readable files. If you absolutely need to view these files, NirSoft has a Chrome and FireFox viewer.

Chrome Cache Location

Chrome browsers currently store caches in the following path:

C:\Users\[username]\AppData\Local\Google\Chrome\User Data\Default\Cache

FireFox Cache Location

FireFox users can view their cache location by accessing about:cache. The latest version of FireFox will show something similar to the following:


If you are looking to analyze performance tradeoffs between different configurations, it may be helpful to use a browser debugger (F12 -> Network) to compare load times:

Cache load times

Cache Validation

Validation is a term used frequently when talking about cache controls and it’s especially important for penetration testers to understand. Directives like no-cache and must-revalidate tell a browser only to use a resource after using ETags or Last-Modified header to check for a newer version:

If-None-Match: "[etag]"


So what Cache Control headers do you need? For secure applications, we generally recommend the following headers:

Cache-Control: no-store
Pragma: no-cache
Expires: -1

Cache controls are defined in RFC 7234, but are not always properly implemented across web clients.

An application penetration test should attempt to reconcile this specification with known behaviors of commonly used browsers. Mitigation steps for this vulnerability should also consider performance requirements and ultimately defer to the business on resolution.

  • Application
  • Network
  • Mobile
  • AWS