Signing Cookies with Vinyl Cache¶
The Problem: A simple example¶
Many web applications accept externally set cookies, enabling all kinds of manipulation, from changing the behavior of a website to security exploits:
A simple example could be a lang cookie, set to either en or de to
render html in either English or German: Understanding the (simple)
structure of the cookie, the user interface language can be changed at will, maybe
even to unsupported languages which the backend does not implement correctly. If
the value of the lang cookie is added to the cache key in Vinyl Cache,
permutating its value can be used to force cache misses.
In this simple example, the solution to check allowed values of lang in VCL
is trivial, but one can easily image cookies where VCL does not or can not know
allowed values.
A slightly more nuanced example is an ordinary session cookie, which is usually
just a hex or base64 encoded nonce: VCL supporting backends offering some kind
of user login will normally switch to pass mode for most URLs if such a
cookie is present. In this case, even if an adversary does not have a valid
session, they can easily force a pass and potentially brute force session IDs,
if they are not sufficiently long and random.
More elaborate scenarios are left to the reader as a research exercise.
The Solution: Signing Cookies¶
So what if we could make sure that only the web application can set valid cookies?
We can by signing them and validating the signature.
We provide here a VCL include which implements the following:
For all
Set-Cookieresponse headers, an expiry timestamp and a signature are added to the cookie value. The expiry timestamp is derived from themax-ageattribute. For session cookies (which do not have the attribute) a customizable default of 30 days is used.All received cookies are validated by
checking the expiry timestamp
verifying that the signature is correct
Only valid cookies are accepted and have the added information (timestamp, signature) stripped off. This way, the application can remain unmodified, because it sees exactly the cookies it set.
To allow signing key rotations, the VCL include supports a transition key via
the cs_signer_transition object.
Summary¶
With this technique, the application only receives cookies it has set itself, which minimizes the attack surface on cookies.
See it in action¶
This technique is used on https://code.vinyl-cache.org:
$ curl -sI https://code.vinyl-cache.org/user/login?redirect_to=%2f | grep -i set-cookie
set-cookie: gitea_incredible=; Path=/; Max-Age=0; HttpOnly; Secure; SameSite=Lax
set-cookie: redirect_to=%2F?1@1783182062?1@az_OrG5w2y-L6X72-MAj4Nvw5XS3wgeTKcUtXN8_tuM; Path=/; HttpOnly; Secure; SameSite=Lax
Here, the redirect_to cookie has ?1@<timestamp>?1@<signature> added.
How to use¶
The VCL include requires the following custom VMODs:
Also, the blob and std bundled VMODs are used.
All mentioned VMODs need to be installed. re2 and objvar need to be
recent as of 2026-02-15 to get the taskvar.strands and re2.hdr_iter
classes.
The VCL include vcl/cookiesign.inc.vcl needs to be installed in a
directory found via vcl_path.
In the main VCL, the following needs to be added:
include "cookiesign.inc.vcl";call cs_recv;must be added early invcl_recvcall cs_backend_response;must be added invcl_backend_responsefor the case thatSet-Cookiehas not been removed (usually for uncacheable responses). When in doubt, just addcall cs_backend_response;at the top.
References¶
This work is used as an example in the presentation WAF: Wrong Approach Firewall at GPN24.
Acknowledgements¶
Development of the VCL code and this documentation has been funded through an in investment of the Sovereign Tech Agency.