Caching 412 responses

Ben Niven-Jenkins <> Sat, 16 February 2013 10:59 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 4C2B021F86C9 for <>; Sat, 16 Feb 2013 02:59:46 -0800 (PST)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -6.599
X-Spam-Status: No, score=-6.599 tagged_above=-999 required=5 tests=[AWL=4.000, BAYES_00=-2.599, RCVD_IN_DNSWL_HI=-8]
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id xSOcrZREUxni for <>; Sat, 16 Feb 2013 02:59:45 -0800 (PST)
Received: from ( []) by (Postfix) with ESMTP id BBF7A21F86C0 for <>; Sat, 16 Feb 2013 02:59:45 -0800 (PST)
Received: from lists by with local (Exim 4.72) (envelope-from <>) id 1U6fSe-0003q4-T5 for; Sat, 16 Feb 2013 10:57:40 +0000
Resent-Date: Sat, 16 Feb 2013 10:57:40 +0000
Resent-Message-Id: <>
Received: from ([]) by with esmtp (Exim 4.72) (envelope-from <>) id 1U6fSX-0003nh-He for; Sat, 16 Feb 2013 10:57:33 +0000
Received: from ([]) by with esmtp (Exim 4.72) (envelope-from <>) id 1U6fSW-0001zV-MN for; Sat, 16 Feb 2013 10:57:33 +0000
Received: from ([] helo=[]) by with esmtpa (Exim 4.71) (envelope-from <>) id 1U6fSA-0003Vx-Ni for; Sat, 16 Feb 2013 10:57:10 +0000
From: Ben Niven-Jenkins <>
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Date: Sat, 16 Feb 2013 10:57:09 +0000
Message-Id: <>
To: HTTP Working Group <>
Mime-Version: 1.0 (Apple Message framework v1085)
X-Mailer: Apple Mail (2.1085)
X-Mailcore-Auth: 9600544
X-Mailcore-Domain: 172912
Received-SPF: none client-ip=;;
X-W3C-Hub-Spam-Status: No, score=-1.9
X-W3C-Hub-Spam-Report: BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001
X-W3C-Scan-Sig: 1U6fSW-0001zV-MN 0886d006c77e87aabd7ff67c8798d381
Subject: Caching 412 responses
Archived-At: <>
X-Mailing-List: <> archive/latest/16619
Precedence: list
List-Id: <>
List-Help: <>
List-Post: <>
List-Unsubscribe: <>


RFC2616 and the HTTPbis drafts allow an intermediary to cache a 412 response to a request with an If-Match header, if the response contains appropriate Cache-Control headers.

My understanding of the specifications is that the intermediary is then within its right to serve the cached 412 response in response to subsequent GET requests that do not contain an If-Match header (see bottom of this mail for an example set of requests/responses that illustrate what I'm trying to describe).

This seems problematic because if an attacker knows an origin returns cacheable 412 responses, the attacker could fill the cache with 412 responses for a set of URLs (from that origin) by making spurious If-Match requests it knows will return 412 responses, and those 412 responses would subsequently be served up to other clients instead of the 'real' response the origin would have given if the 412 was not cacheable or if the attacker had not poisoned the intermediary's cache with 412s.

I was wondering whether this is a gap in the spec and cacheable 412 responses should have an explicit (or implicit?) Vary: If-Match semantic associated with them?

Or, whether it is purposely the way it is and is a case of providing the rope and letting people hang themselves if they so choose (Origin servers can always add the Vary: header if they care about cache poisoning, intermediaries can always not cache 412 responses, etc.).

An example (with only the relevant Headers included for compactness) of what I am talking about would be:

First request:
GET /foo HTTP/1.1
If-Match: "thisisnotanetag"

HTTP/1.1 412 Precondition Failed
Cache-Control: max-age=900 of response...

Subsequent request:
GET /foo HTTP/1.1

HTTP/1.1 412 Precondition Failed
Age: 10
Cache-Control: max-age=900 of response...