GET /cookie
Returns malformed Set-Cookie headers that real-world clients silently drop, accept differently, or argue about. Ten modes covering SameSite, expiry, prefix, folding, domain, and CHIPS violations.
mode
Which flaw to send. samesite-none-no-secure (default; SameSite=None without Secure, browsers reject), expiry-contradiction (past Expires + future Max-Age), multiple-same-name (three Set-Cookie headers with the same name), bad-path (cookie scoped to a path not served), huge-value (~8KB, over the 4KB limit), host-prefix-violation (__Host- with Domain= set, violates RFC 6265bis), secure-prefix-violation (__Secure- without Secure attribute), comma-folded (two cookies joined in one header with comma, excluded by RFC 6265), domain-overreach (Domain=catastrophic.io from chaos.catastrophic.io subdomain), partitioned-no-secure (Partitioned without Secure, CHIPS requirement violated).
build a request:
expect: 200 OK with one or more Set-Cookie headers crafted to break in the chosen way. X-Chaos-Cookie-Mode reflects the selection; the JSON body explains what's wrong.
curl -i 'https://chaos.catastrophic.io/cookie?mode=samesite-none-no-secure'
import urllib.request
resp = urllib.request.urlopen("https://chaos.catastrophic.io/cookie?mode=samesite-none-no-secure")
print(resp.status, resp.headers["X-Chaos-Cookie-Mode"])
# Note: get_all returns every Set-Cookie when there are duplicates
for c in resp.headers.get_all("Set-Cookie") or []:
print("Set-Cookie:", c)
// Browser fetch hides Set-Cookie from JS; use Node's http for visibility.
const res = await fetch("https://chaos.catastrophic.io/cookie?mode=samesite-none-no-secure");
console.log(res.status, res.headers.get("x-chaos-cookie-mode"));
// res.headers.get('set-cookie') only returns the first in browsers.
console.log(await res.text());
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
resp, _ := http.Get("https://chaos.catastrophic.io/cookie?mode=samesite-none-no-secure")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(resp.StatusCode, resp.Header.Get("X-Chaos-Cookie-Mode"))
for _, c := range resp.Header.Values("Set-Cookie") {
fmt.Println("Set-Cookie:", c)
}
fmt.Println(string(body))
}
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking"] }
fn main() -> Result<(), Box> {
let resp = reqwest::blocking::get("https://chaos.catastrophic.io/cookie?mode=samesite-none-no-secure")?;
println!("{} {:?}", resp.status(), resp.headers().get("x-chaos-cookie-mode"));
for c in resp.headers().get_all("set-cookie") {
println!("Set-Cookie: {:?}", c);
}
Ok(())
}
import java.net.URI;
import java.net.http.*;
public class CookieChaos {
public static void main(String[] args) throws Exception {
var client = HttpClient.newHttpClient();
var req = HttpRequest.newBuilder(URI.create("https://chaos.catastrophic.io/cookie?mode=samesite-none-no-secure")).build();
var resp = client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.statusCode() + " " +
resp.headers().firstValue("X-Chaos-Cookie-Mode").orElse(""));
resp.headers().allValues("Set-Cookie").forEach(c ->
System.out.println("Set-Cookie: " + c));
}
}
using var client = new HttpClient();
var resp = await client.GetAsync("https://chaos.catastrophic.io/cookie?mode=samesite-none-no-secure");
resp.Headers.TryGetValues("X-Chaos-Cookie-Mode", out var mode);
Console.WriteLine($"{(int)resp.StatusCode} {mode?.FirstOrDefault()}");
if (resp.Headers.TryGetValues("Set-Cookie", out var cookies))
{
foreach (var c in cookies) Console.WriteLine($"Set-Cookie: {c}");
}
require "net/http"
res = Net::HTTP.get_response(URI("https://chaos.catastrophic.io/cookie?mode=samesite-none-no-secure"))
puts "#{res.code} #{res['X-Chaos-Cookie-Mode']}"
res.get_fields("Set-Cookie")&.each { |c| puts "Set-Cookie: #{c}" }
# PowerShell's Invoke-WebRequest collapses duplicate Set-Cookie headers;
# use the raw HttpClient to see all of them.
$r = Invoke-WebRequest -Uri 'https://chaos.catastrophic.io/cookie?mode=samesite-none-no-secure'
$r.Headers['X-Chaos-Cookie-Mode']
$r.Headers['Set-Cookie']
$r.Content
headers
body