Closed Bug 252023 Opened 20 years ago Closed 20 years ago

"no-store" header directives from server or web script ignored by browser during non-SSL transactions

Categories

(Core :: DOM: Navigation, defect)

x86
Linux
defect
Not set
major

Tracking

()

RESOLVED FIXED
mozilla1.8beta1

People

(Reporter: kenh2000, Assigned: darin.moz)

References

Details

(Keywords: fixed-aviary1.0, fixed1.7.5, regression)

Attachments

(1 file, 1 obsolete file)

User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040113
Build Identifier: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040113

The "Cache-Control: no-store" header (whether produced by the server or the 
php script) is ignored by the Mozilla browser-1.6 (regardless of the Cache -
network comparison setting in the Preferences section of the browser) during
non-SSL browser-server interaction. 

If a form is sent to the browser with this header and subsequently submitted,
the user
can retrieve the form WITH its text fields containing the previously submitted
text by
using the "Back" instruction of the browser.

The above problem does not occur when using Internet Explorer on a separate PC on
the network i.e. hitting the "Back" button causes an end-to-end reload from the
server and correctly supplies a new blank form.

I note from the following link that Mozilla caches script output despite "no-cache"
headers (see http://www.mozilla.org/projects/netlib/http/http-caching-faq.html).

This problem also occurs even if one uses header combinations such as those
below to force non-caching and an end-to-end reload even in the presence of a
"no-cache" directive:

header("Expires Fri, 19 Apr 2002 00:00:00 GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Pragma: no-cache");

or another example such as this:

$script_filemtime = filemtime($_SERVER['SCRIPT_FILENAME']);
/* filemtime() error -- set at current time minus approx 3 years */
if (!$script_filemtime) $script_filemtime = time() - 24*3600*1000;

/* back date filemtime by approx 7 years */
header("Last-Modified: ".gmdate("D, d M Y H:i:s",
$script_filemtime-24*3600*2600)." GMT"); 
/* back date expiry by approx 6 years */
header("Expires: ".gmdate("D, d M Y H:i:s", $script_filemtime-24*3600*2200)."
GMT");  
header("Cache-Control: no-store, no-cache, must-revalidate"); 
header("Pragma: no-cache"); 

Software used:

Apache 2.0.48 with mod_php (4.3.4) and mod_ssl
Redhat Linux 9.0
Mozilla 1.6
MySQL 4.0.18 

Hardware

Gigabyte GA-7VTXE mb
1 Gig DDR ram
Duron 800 MHz CPU
Maxtor 20 Gig IDE HD
Linksys lne100tx v5.1 network card

This is potentially a serious security problem if the browser is used to
submit forms where SSL is not used eg. using a form to submit e-mail
to a mailing program, entering medical information in a form where the PC may be
part of an intranet and entered information is not being submitted via SSL. Once
the information is submitted, the user wants to be sure that someone else can't
come 
along and use the "Back"  button to "snoop" at previously submitted information.

If a developer uses a "no-store" header, then he / she wants to be confident that
the directive will be obeyed by the browser and information entered into a form is
not cached for someone else to "snoop" at it by simply using the "Back" directive of
the browser. This is a particularly important issue if the form is being used to
enter sensitive data e.g. medical, legal or financial data by users on an intranet /
LAN.

The browser should strictly obey "no-store" directives according to rfc2616,
section 
14.9.2 "What May be Stored by Caches" i.e. if the developer puts a "no-store" header
in the script, don't store it on disc (or in ram once the page is actually in
the video buffer for display). Ditto for "no-cache" directives regarding rfc2616.

Reproducible: Always
Steps to Reproduce:
See "Details"
Actual Results:  
See "Details"

Expected Results:  
no-store, no-cache (expired) pages should not be cached i.e. users should not be
able to retrieve "non-stored" or "non-cached" forms with their associated text
by simply 
clicking the "Back" button
No-store was implemented in bug 92598, but is only preventing that the data is
store in the disk-cache, not the memory-cache.

The problem is that RFC2616 is contradictory. See para 14.9.2 (the same one !) :
      Even when this directive is associated with a response, users
      might explicitly store such a response outside of the caching
      system (e.g., with a "Save As" dialog). History buffers MAY store
      such responses as part of their normal operation.

Mozilla needs the in-memory cache for session history (back/forward buttons),
file->save_as, and view->page_source. Security sensitive pages don't want that,
but then we have to disable all this.
"no-store" should disable form state restoration, we have code to that effect,
and in my testing it works.

Ken, is there a particular site showing the problem?  Can you reproduce the
problem in a current build?
Can someone update the status of this bug? UNCONFIRMED as of 2004-09-15.

I have a similar problem, but I did not know about no-store (I guess I have to
read HTTP spec from beginning to the very end). I use the following response
headers: "Pragma: No-cache", "Cache-Control: no-cache", "Expires: Thu, 01 Jan
1970 00:00:00 GMT". The page is not reloaded on "Back", and I was told that
no-store should help for it to get reloaded. Does it work now (in Firefox)?
I tested Firefox 1.0PR, and I was able to reproduce the bug.  I reproduced it
when Cache-control: no-store was specified as a HTTP header as well as when it
was specified as a HTTP-EQUIV in a <META> tag.  Oops!!
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true
Target Milestone: --- → mozilla1.8beta
From a network log, it's apparent that pressing the Back button to go back to a
no-store form page results in a new network load.  The page is completely
loaded, but for some reason, the form is still pre-filled!  Something must be
going wrong in the docshell code.  (I'm testing an firefox 1.0 branch build.)
Attached patch v1 patch (obsolete) — Splinter Review
This patch fixes the bug.  I'm not sure what triggered this regression
originally, but it is clear that the session history code is extremely fragile
since it does not assert that layout history state is not saved when it has
been told not to save layout history state.  I can only imagine that at some
time in the past we must have been checking GetSaveLayoutHistoryStateFlag
before calling SaveLayoutHistoryState or something.  That archeology is not
that interesting to me.  This patch is the right thing since it ensures that we
always honor the SaveLayoutHistoryStateFlag.

I verified that this fixes both the server header case as well as the
HTTP-EQUIV case.

I'm not sure if we want to ASSERT or just WARN if the API is misused.  Or maybe
we want to silently fail.  Or maybe we should fix the callsites to check the
flag first.  Not sure... boris: what do you think?
Attachment #159053 - Flags: superreview?(bzbarsky)
Attachment #159053 - Flags: review?(bzbarsky)
-> History: Session
Component: Networking: Cache → History: Session
Flags: blocking1.7.x?
Flags: blocking-aviary1.0?
Keywords: regression
Comment on attachment 159053 [details] [diff] [review]
v1 patch

I think asserting here is fine.  r+sr=bzbarsky.
Attachment #159053 - Flags: superreview?(bzbarsky)
Attachment #159053 - Flags: superreview+
Attachment #159053 - Flags: review?(bzbarsky)
Attachment #159053 - Flags: review+
fixed-on-trunk
Status: ASSIGNED → RESOLVED
Closed: 20 years ago
Resolution: --- → FIXED
Comment on attachment 159053 [details] [diff] [review]
v1 patch

this is a must fix bug.
Attachment #159053 - Flags: approval1.7.x?
Attachment #159053 - Flags: approval-aviary?
> I think asserting here is fine.  r+sr=bzbarsky.

note that NS_ENSURE_* does warn, not assert.
this patch caused bug 260314.
Depends on: 260314
This patch includes the minimal fix required for bug 260314.  This is the patch
we should land on the 1.7 and Aviary branches.
Attachment #159053 - Attachment is obsolete: true
Attachment #159654 - Flags: superreview?(bzbarsky)
Attachment #159654 - Flags: review?(bzbarsky)
Comment on attachment 159654 [details] [diff] [review]
v1.1 patch - for the 1.7 and aviary branches

Looks ok.  r+sr=bzbarsky
Attachment #159654 - Flags: superreview?(bzbarsky)
Attachment #159654 - Flags: superreview+
Attachment #159654 - Flags: review?(bzbarsky)
Attachment #159654 - Flags: review+
Attachment #159654 - Flags: approval1.7.x?
Attachment #159654 - Flags: approval-aviary?
Attachment #159053 - Flags: approval1.7.x?
Attachment #159053 - Flags: approval-aviary?
Comment on attachment 159654 [details] [diff] [review]
v1.1 patch - for the 1.7 and aviary branches

a=asa for branches checkin.
Attachment #159654 - Flags: approval1.7.x?
Attachment #159654 - Flags: approval1.7.x+
Attachment #159654 - Flags: approval-aviary?
Attachment #159654 - Flags: approval-aviary+
fixed-aviary1.0
Keywords: fixed-aviary1.0
fixed1.7.x
Keywords: fixed1.7.x
Flags: blocking1.7.x?
Flags: blocking-aviary1.0?
Is it really fixed in Firefox 1.0, released in November? Granted, I have not
tried to modify the response headers themselves, but I added http-equiv tags to
my HTML pages and it seems not to work.

Here is what I put into my page: 
<head>
  <meta http-equiv="Cache-Control" content="no-store,no-cache,max-age=-1">
  <meta http-equiv="Pragma" content="no-cache">
  <meta http-equiv="Pragma" content="no-store">
  <meta http-equiv="Expires" content="-1">
</head>

Firefox still caches the page when I click Back button. Is something wrong with
the meta tags? Is there a recommendation from Mozilla developers how to write
"no-cache/no-store" tags?

Platform: Win 2000.
> but I added http-equiv tags to my HTML pages

That does absolutely nothing in this case unless your server converts those into
actual headers like it's supposed to.
we do attempt to support those in meta tags.  the problem with no-store is that
we should not be storing the content on disk, but we start storing it on disk
before we encounter no-store.  hence, it may be the case that we leave it on
disk.  we should probably doom the entry in that case instead of leaving it on
disk.  can you please file a new bug about no-store in a meta tag?

i believe our current behavior is to mark the disk cache entry to immediately
expire so that we'll request a validation request the next time it is encountered.
I know this is not the place for Q&A, and a simple user as I am, must ask this
question somewhere on Mozillazine, but I would like to have a consise answer
from gurus :) Maybe later you will include it in the FAQ.

If I understand current policy for session history cache correctly,
Mozilla/Firefox identifies resources by their Base URL + [query string | post
data]. Page content is not evaluated. Combined with my current knowledge of
"no-store" directive, caching and browsing history looks something like this:

If page is considered cacheable:
 * Its location is added to session history
 * Its content is cached for history purposes
 * Its content is cached for "view source" and "save as"
 * Its content is cached if directly accessed by location
 * Its content is reloaded on "Reload" command

If page is marked "no-cache":
 * Its location is added to session history
 * Its content is cached for history purposes
 * Its content is cached for "view source" and "save as"
 * Its content is reloaded if directly accessed by location
 * Its content is reloaded on "Reload" command

If page is marked "no-store" || "no-cache" & SSL:
 * Its location is added to session history
 * Its content is NOT cached for history purposes
 * Its content is cached for "view source" and "save as"
 * Its content is reloaded if directly accessed by location
 * Its content is reloaded on "Reload" command

If different content is served from the same exact location
(that is, Base URL + [query string | post data]):
 * The location is NOT added to session history, 
   because the session cache key is the same.
   (AFAIK, Opera adds all loaded resources to the history,
   which I really dislike. I want to make sure that current 
   Mozilla behavior will not change in the future).

If an agent is redirected to a different location using 303 code:
 * Original location is NOT added to session history,
   this does not depend on original request type (POST or GET)
   (Will this change in the future?) 
 * Redirected resource is always loaded using GET method

If an agent is redirected to a different location using 302 code:
 * Original location is NOT added to session history,
   this does not depend on original request type (POST or GET) 
 * Redirected resource is loaded using GET method to
   provide compatibility with older agents and with many
   server-side applications (apparently, this will never be 
   changed in the future?)
"no-store" || ("no-cache" & SSL), of course
Component: History: Session → Document Navigation
QA Contact: networking.cache → docshell
You need to log in before you can comment on or make changes to this bug.