cols: guess byte 0x00→0xFF
crypto.subtle (requires a secure context). Reload over HTTPS.crypto.subtle (requires a secure context). Reload over HTTPS.Before TLS 1.3, browsers negotiated CBC-mode block ciphers whose record layer decrypted each 16-byte block as DK(Ci) ⊕ Ci−1 and then stripped PKCS#7 padding — and if a server ever signalled, even indirectly through timing, whether that padding came out valid, it handed an attacker a one-bit oracle per query. This simulator runs the attack for real: it generates a fresh AES-128 key with crypto.subtle.generateKey, encrypts a random 16-byte secret block with a random IV, and then recovers that secret byte-by-byte using nothing but padding-valid/invalid responses from crypto.subtle.decrypt — the same primitive a real vulnerable TLS server exposes. The 2D lattice renders the actual 256-guess search at every byte position as it happens, so the fill pattern you see is the real geometric query-cost distribution, not a canned animation. Switch to AEAD/GCM to see why the same attack is instantly rejected: authenticated encryption checks the integrity tag before touching the padding at all, which is exactly why TLS 1.3 made AEAD ciphers mandatory and dropped CBC suites entirely.