Hello fellow humans, AIs, and super-intelligent shades of the color blue,
Today we released Sunlight v0.8.1, a security fix for v0.8.0.
Summary. The Sunlight deduplication cache used 128-bit keys, which potentially allowed obtaining SCTs for forged certificates. In the WebPKI, this would have required a colluding, compromised, or separately vulnerable CA. Tuscolo, Willow, and Sycamore have rolled out the patch. Gouda is scheduled to roll out the patch soon.
Details. Submissions were deduplicated by looking them up in a SQLite database using a SHA-256 hash truncated to 128 bits. If a match is found in the deduplication cache, Sunlight signs an SCT over the stored (old) timestamp and index, and the submitted (pre-)certificate. With 128-bit keys, an attacker could compute a collision offline in 2⁶⁴ work (costing in the order of tens of thousands of dollars), submit an honest certificate, and then obtain an SCT for the colliding certificate, without the latter making it into the log.
Mitigating factors. This is a collision attack, so it requires selecting a pair of certificates which happen to randomly have the same truncated SHA-256 hash from a large pool of 2⁶⁴ candidates. In the WebPKI, this attack would require a colluding, compromised, or separately vulnerable CA, because the TLS BRs require unpredictable entropy in the serial number, making it impossible to compute the collision offline.
Remediation. Sunlight v0.8.1 now only inserts new entries in the cache using their full SHA-256 hash, in a new "cache256" table. Existing 128-bit keys are still queried, to avoid a wave of cache misses when upgrading from v0.8.0 (or earlier) to v0.8.1 (or later). This is relatively safe because a collision attack requires control over both entries. Either the attack was executed in the past, in which case the attacker already obtained a forged SCT, or the existing 128-bit keys are honest. With approximately 2³² honest entries in the cache, a multi-target second preimage attack that searches for a new certificate that matches one of them would require 2⁹⁶ work (taking in the order of a couple years with the same energy consumption as the whole Bitcoin network).
For extra safety, operators can optionally run the new recompute-cache command to rebuild the cache with 256-bit keys from the backend storage (with verification of the STH, not to trust the backend). Once recompute-cache has completed, running
sqlite3 cache.db "ALTER TABLE cache RENAME TO cache_legacy;"
disables the fallback. This is safe to run concurrently with the log. (Do not use DROP as that would be a long write transaction, which would block the sequencer. Ask me how I know. Poor Navigli.)
The Tuscolo logs have rolled out the patch, regenerated the cache, and disabled the fallback. I am told the Willow and Sycamore logs are now running v0.8.1, and that the Gouda rollout is planned for 22:30 CEST. I'd like to thank the Sunlight operators for their rapid response.
Retrospective. The deduplication cache implementation was probably too clever. It uses deterministic ECDSA to produce byte-identical SCTs without storing the signatures. I felt pressure to limit the on-disk size of this cache, because it needs to live locally, even in setups that use object storage for the log. That was probably over-indexed in retrospect: the Tuscolo2025h2 cache is 70GB. I also apparently did think about collisions, because the cache type had a comment saying
// birthday bound of 2⁴⁸ entries with collision chance 2⁻³²
but I failed to realize that intentional collisions were both possible and valuable to an attacker. Besides being less clever with the cache, it's not clear how else this could have been prevented without hindsight. Suggestions are welcome.
Timeline.
- 2026-06-10: the issue is spontaneously reported by Anthropic, along with lower severity issues in Sunlight and age. The issue is reported as severity LOW. Upon a first skim, I fail to recognize the actual severity, and defer it.
- 2026-06-25: upon triaging the issue, I identify its severity, and coordinate with other Sunlight operators on a suitable release date. (No details of the vulnerability were disclosed to the operators.) Tuesday is selected to avoid US and Canada holidays.
- 2026-06-27: fix deployed to the Navigli staging logs.
- 2026-06-28: fix deployed to the Tuscolo production logs.
- 2026-06-30: public release, fix deployed to Willow and Sycamore; Gouda deployment planned for 22:30 CEST.
Credit. This vulnerability was discovered by Claude, Anthropic's AI assistant, and triaged by the Anthropic security team in collaboration with Anthropic Research.
Alla prossima (well, hopefully not),
Filippo