A compression oracle attack recovers a secret by watching how long a ciphertext is, not by breaking the cipher. It works whenever a system compresses data and then encrypts it, and an attacker can place their own guess next to the secret in the same compressed buffer. Compression shrinks repeated text, so when the attacker’s guess matches part of the secret, the two copies collapse together and the output gets shorter. A shorter ciphertext means the guess was right. This is the class behind the named CRIME and BREACH attacks, and it belongs to the wider family of cryptographic oracle attacks.
How a compression oracle attack leaks a secret
Start with how compression works. A common algorithm replaces a repeated run of bytes with a short back reference that says copy this many bytes from that far back. Two identical strings near each other compress to far less than two separate strings. The more the input repeats, the smaller the output.
Now add encryption. The stream and counter based modes that protect most web traffic keep the plaintext length, give or take a small fixed amount. So the ciphertext length closely tracks the compressed length, which tracks how repetitive the plaintext was. The cipher hides the content but not the size, and size is the leak.
The attacker needs two things in the same compressed buffer: a secret they want, such as a session token, and a field they control. Picture an invented app, Acme Notes, that reflects a search term into a page that also contains the user’s token, then compresses and encrypts the whole response. The attacker sets the search term to a guess at the token and measures the response size.
secret in the buffer: token=s3cr3t attacker controlled guess placed beside it: guess "token=a" -> little overlap -> longer output guess "token=b" -> little overlap -> longer output ... guess "token=s" -> "token=s" now appears twice -> shorter output
The guess that makes the response shortest shares the longest run with the secret, so its last character is almost certainly the next character of the token. Lock that character in, move to the next position, and repeat. The secret falls one byte at a time. The attacker never decrypts anything. They only compare lengths.
Encryption hid every byte of the secret and leaked the one thing that still mattered, how many of those bytes the attacker had already guessed.
Why compressing before encrypting is the trap
The order is the whole problem. Compress then encrypt, and the ciphertext length reveals the plaintext redundancy. The named attacks differ only in where the compression sits. One targeted compression applied at the transport layer, below the application. The other targeted compression applied to web responses, which is common because it saves bandwidth. In both, a secret and attacker controlled data rode in the same compressed stream, and the length told the rest of the story.
To make a guess cheap to test, the attacker usually needs many requests and a way to observe each response size, for example as a network observer or through a side channel that reveals length. The defense does not depend on blocking that view. It depends on making length say nothing about the secret.
How to defend against it
The fixes all come down to keeping the secret and the attacker’s input out of the same length signal.
- Do not compress secret and attacker controlled data together. This is the core rule. If a response mixes a token with reflected user input, either do not compress it or do not put the secret there.
- Turn off compression for sensitive responses. For pages and API replies that carry secrets, the bandwidth saved is not worth the leak. Disable it on those paths.
- Separate contexts. Compress attacker influenced content in a buffer that contains no secret, and keep secrets in their own context that the attacker cannot add repeated text to.
- Hide length. Add random padding so the output size no longer tracks the compressed size closely. This costs bandwidth and only blurs the signal, so treat it as a backstop, not a primary fix.
- Make a guessed secret useless. Rotate or mask tokens per request, the way an anti forgery token is randomized each time, so that even a recovered value does not replay. A secret that changes every request cannot be rebuilt one slow byte at a time.
The same length leak pairs naturally with stream ciphers, which preserve plaintext size exactly, a theme you can see from the other direction in keystream reuse. For where this sits among everyday web bugs, see vulnerability basics.
The assumption that breaks
A compression oracle attack is a clean example of a secret leaking through a channel nobody thought to protect. The cipher did its job. The developer added compression to save bytes, a reasonable choice on its own, and never considered that the output size would carry information about a secret sitting in the same buffer. Finding this means tracing what data shares a compression context and asking whether its length depends on something private, rather than scanning for a known bad function. That kind of reasoning about how an app really handles data is what an autonomous researcher like UnboundCompute is built to do. Read more on our about page.
Frequently asked questions
What is a compression oracle attack?
It is an attack that recovers a secret by watching ciphertext length rather than breaking the cipher. When a system compresses data before encrypting it, and an attacker can place a guess next to the secret in the same compressed buffer, a matching guess makes the output shorter. A shorter ciphertext means the guess was right, so the secret leaks byte by byte.
Why does compressing before encrypting leak a secret?
Compression shrinks repeated text, so the output size depends on how repetitive the input was. Stream and counter based encryption keep the plaintext length, so the ciphertext size tracks the compressed size. The cipher hides the content but not the size, and when a secret and attacker input share a buffer, the size reveals how much they overlap.
Are CRIME and BREACH compression oracle attacks?
Yes. Both are named members of this class. They differ only in where the compression sits. One used compression applied at the transport layer below the application, and the other used compression applied to web responses. In both a secret and attacker controlled data rode in the same compressed stream, and the length told the rest.
How do you defend against a compression oracle attack?
Keep the secret and the attacker’s input out of the same length signal. Do not compress responses that mix a token with reflected user input, turn off compression for sensitive paths, separate compression contexts, add random padding to blur length as a backstop, and rotate or mask tokens per request so a recovered value cannot replay.
Put an autonomous researcher on your own systems
UnboundCompute is an autonomous security researcher that reasons about how an application fits together and proves the access control and injection bugs it finds. We are opening a small number of founding design partner seats: private early access pointed at a staging target you choose, and a say in what it looks for. If your team ships software worth pressure testing, apply to the design partner program.
