Please read my blog's comment policy here.
From time-to-time, I get questions about Internet Explorer’s behavior when it comes to caching of HTTPS-delivered content.
It comes as a surprise to many that by-default, all versions of Internet Explorer will cache HTTPS content so long as the caching headers allow it. If a resource is sent with a Cache-Control: max-age=600 directive, for instance, IE will cache the resource for ten minutes. The use of HTTPS alone has no impact on whether or not IE decides to cache a resource. (Non-IE browsers may have different default behavior for caching of HTTPS content, depending on which version you’re using, so I won’t be talking about them.)
Now, having said that, there are a few caveats to be aware of.
First, the Internet Options control panel’s Advanced tab includes an option “Do not save encrypted pages to disk.” When this option is set, caching directives from the server are ignored, and HTTPS-delivered resources will not be cached for reuse, even during the same browser session.
This option is unticked by default on all client versions of Windows, but is ticked by default on the Windows Server versions. Hence, most of your sites visitors will not have this option set. However, the option is occasionally set by Group Policy as an attack-surface-reduction measure, although the side-effects of doing so can be pretty dire. The problem is that this option makes SSL-delivered downloads uncacheable by default, and that can lead to the dreaded “Internet Explorer cannot download” dialog. Rather than use this option, I recommend you use BitLocker Drive Encryption and/or use the Delete Browser History on Exit option.
The second caveat to be aware of relates to an obscure architectural artifact in WinINET/IE. WinINET will not reuse a previously-cached resource delivered over HTTPS until at least one secure connection to the target host has been established by the current process. This can lead to previously-cached resources being ignored, leading to increased network requests.
Some examples are in order.
Test Page #1 is a page at https://www.fiddler2.com which contains 5 embedded images. Four of the five images on the page are marked as cacheable. The cacheable images come from https://www.fiddler2.com, https://fiddler2.com, and https://login.live.com.
Internet Explorer had already established a secure connection to https://www.fiddler2.com during this browser process' lifetime—when it downloaded the test page itself. On the other hand, https://login.live.com and https://fiddler2.com had not been contacted by this browser process, so their cached resources were ignored.
As you can see from this example, the simplest strategy to avoid the WinINET artifact is to ensure that if you have a page at https://www.example.com, it only tries to download cacheable resources from itself (https://www.example.com). Since a secure connection will be established when downloading the page itself, before any of its resources are downloaded, you’re guaranteed that the cache will not be bypassed.
Test Page #2 is the same page at a different host, http://www.enhanceie.com, and it contains the same 5 embedded images.
Because this Internet Explorer process hasn’t previously contacted any of the secure servers, it will bypass the cache for all of the images.
Now, at this point, alert readers will shout “Hey, wait a second!”
They’ll note: “Two of those images came from the same secure server. So shouldn’t the second image get pulled from the cache because the first image resulted in the server getting contacted?” And sadly, the answer here is “Not in this case.” The problem is that the two network requests are sent in parallel, so the cache has already been bypassed for the second request before the first request secure connection to the server has been established. In this surprising example, parallelism in the network stack leads to slower overall performance.
Having said that, this strategy can act as a workaround for the cache-bypassing behavior. If you construct your page such that it doesn’t make subsequent network requests to a cross-domain HTTPS server until the first response is returned, you will find that cached resources are reused for all subsequent requests to that HTTPS server for the life of the browser process.
7/14/2010 Update: The situation is improved in IE9; IE9 will make conditional HTTPS requests instead of unconditional requests. Additionally, the problems mentioned in Internet Explorer cannot download have been resolved so long as the Tools > Internet Options > Advanced > "Do not save encrypted pages to disk" option is not set.
6/1/2012 Update: The situation is improved (basically resolved) in IE10. IE10 does not force a connection to the origin HTTPS server for sub-downloads if the sub-downloads are in the cache and within their freshness lifetime.
Until next time,
 It doesn't matter whether that first secure connection is still alive; it's enough that it was ever established during the lifetime of the current process.
Very interesting Eric!
I just tested this on the homepage of the largest ISP in The Netherlands (first visit > close browser > second visit) and see it happen: the two stylesheet files are *both* downloaded, and not fetched from the cache.
Txs for the insight.
Why does the option have to be not caching https requests and caching https requests in cleartext files on the harddrive? Can't IE use EFS on all saved/cached files from a https source? (assuming the cache is on a NTFS partition) Delete history on exit doesn't seem that secure as it leaves the files avalible to be undeleted and bitlocker doesn't provide protection between users on the box.
@Eli: Solutions like BitLocker are the way to ensure that your cache files (and everything else, for that matter) are not exposed if your hardware is stolen. As for "protection between users on the box"-- Windows NTFS ACLs are the solution to that threat.
It's also worth mentioning that the bulk of content delivered over HTTPS isn't really "secret" in any way-- it's made up of images, CSS, JS, etc. Only on per-user pages (e.g. the HTML itself) is it worthwhile to consider no-cache directives.
As for the "Delete Browser History on Exit suffers from an undelete risk" threat-- wiping free space on shutdown is one mitigation here. Typically, an attacker who has the level of access to undelete files can execute other, more sinister attacks.
I just stumbled across this blog - very useful! We need to find out the following from Microsoft:1. Are the SSL pages cached on disk in an encrypted fashion. If so, who can read them? The comments above seem to confirm that https requests are not encrypted on disk but are in cleartext.2. When does a cached SSL page expire?3. Can you override at an admin level when the page expires? Thanks!
@Sam: If you have enabled BitLocker or other full-drive encryption, then the pages are encrypted. If you don't, they are not. (It's worth mentioning that full-disk encryption is ALWAYS a best-practice for unsecured clients, because nearly *anything* that the system ever has in memory could end up in the page file on disk).
Cached HTTPS pages expire according to the rules of HTTP, which in turn are described in RFC2616. Administrators can use scripts to delete the cache (or even disable caching of HTTPS altogether) with the caveat that doing so can cause functionality problems (e.g. sites may not work, as described in this post).
Eric, do you have an article detailing how the WinInet Caching mechanism works in general, below the hood?
@Toni: What questions do you have? My latest post on caching is here: blogs.msdn.com/.../caching-improvements-in-internet-explorer-9.aspx
@Toni: I hate to be a wet blanket, but the entire approach is "wrong" insofar as what you're doing isn't supported, and is subject to break in any monthly update to Internet Explorer. Hacking on private interfaces ("API hooking") is not supported as it is fragile and often introduces reliability and security problems.
Eric, totally understand the issues associated with API hooking - but any alternatives you would recommend (besides app virtualization?)
I am not experiencing the behaviour you have described above "If you close IE and reopen it to the test page, you will find there are 4 unconditional requests: 1 for the page". When I close IE and reopen the test page it is making 6 unconditionally requests (5 return 200 OK and 1 404 Not found - login.live.com image). I am using IE 8 and have my browser cache settings to automatic. When I click reload it is only requesting the main page, the uncached image and the login.live.com image, so I assume the other images are being cached correctly. If I F5 the browser makes all 6 unconditionally requests again. I would've thought it would make conditional requests (and 304 responses) for the cached images but this is not happening. I really need to understand how to make static content (css, png, js, etc) cached over ssl between IE browser restarts. Thanks Stu
@Stuart: Feel free to send me a Fiddler log showing what you're seeing. Generally speaking, F5 and clicking refresh do exactly the same thing (and neither makes the request unconditional), so I suspect perhaps you have a plugin or something that is interfering with your traffic.
@Eric - thanks for the speedy reply. I was actually using a different http debugger (Http Debugger Pro 4.3) which was showing a HTTP 200 response each time for the cached images (on browser re-start). I don't think this tool uses a proxy to capture requests / responses so not sure how it works. I have since used fiddler2 and can see that the cached images (1 and 2) are not refreshed on browser restart (desired behaviour). I will continue to do some testing on a local IIS instance and interrogate the IIS logs to trace actual requests and responses, but it looks like your article suggesting moving static content to the same domain as the main pages will sort my caching woes. Thanks again.
@Eric, does it mean that there is almost no chances for IE to cache ssl.google-analytics.com/ga.js as popular example? :-( We had experimented with separate host for our CSS and images and looks like must postpone now until IE9 and other browsers will grab more popularity...
@Alex: I'm not sure how you would arrive at that conclusion.