safari-binarycookies
A small, dependency-light, #![forbid(unsafe_code)] Rust library for decoding the Safari / WebKit Cookies.binarycookies cookie-jar format used on macOS and iOS (for example ~/Library/Cookies/Cookies.binarycookies). Byte-level behavior is kept in parity with the Go reference implementation moond4rk/binarycookies and verified against golden files it generates.
- Dependency-light, safe core —
std+time+thiserror,#![forbid(unsafe_code)], nobyteorder/nom. - Synchronous, sans-IO core — read a buffer, decode it; no async runtime.
- Hardened against crafted input — any malformed file returns an
Err, never a panic; counts are capped before allocation. - Opt-in extras —
serde(RFC 3339 timestamps) anddisplaybehind additive features.
Usage
Decode a cookie jar from disk and walk every cookie:
#
#
Or stream cookies lazily from an in-memory buffer with cookies, which flattens the page layer:
// A minimal valid file: `cook` magic + zero pages + 8-byte checksum.
let data = *b"cook\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
let jar = from_bytes?;
assert!;
let cookies: = cookies?.collect;
assert!;
# Ok::
API at a glance
| Item | Description |
|---|---|
from_bytes(&[u8]) |
Sans-IO core: decode a complete buffer into BinaryCookies |
cookies(&[u8]) |
Lazy Iterator<Item = Result<Cookie, Error>> over all pages |
from_reader(R) / from_path(P) |
Convenience readers (std feature, on by default) |
BinaryCookies / Page / Cookie / Flags |
Plain data types with public fields |
BinaryCookies::cookies() |
Borrowing iterator over every cookie, flattening the page layer |
Cookie::{is_secure, is_http_only, expires_unix, creation_unix} |
Convenience accessors |
Feature flags
| Feature | Default | Effect |
|---|---|---|
std |
✅ | Enables from_reader / from_path; the core decoder works without it |
serde |
— | Serialize / Deserialize for all data types, timestamps as RFC 3339 |
display |
— | impl Display for Cookie, timestamps rendered in UTC |
Disabling std only removes the I/O constructors (from_reader / from_path); the crate is not no_std — std itself is always linked.
Format notes
- Counts and sizes mix endianness by region: the file header is big-endian, everything inside pages is little-endian, timestamps are little-endian
f64seconds since the Mac epoch (2001-01-01). - The trailing 8-byte checksum is stored but never verified, and bytes after it (usually a
bplist00with the cookie accept policy) are ignored — both matching the Go reference implementation. - Out-of-range timestamps in crafted files are clamped to the years ±9999 range supported by
time; NaN decodes to the Unix epoch.
License
Licensed under the Apache License, Version 2.0.
Attribution
This crate is a Rust port of the Go implementation at moond4rk/binarycookies, itself a hardened fork of cixtor/binarycookies (Copyright (c) 2019 CIXTOR). Provenance notes are kept in the source as NOTES(cixtor) comments.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be licensed as above, without any additional terms or conditions.