> Can't do much about that one. Gotta have someone telling you, or (worst case) the very state of the art advancing under your feet.
But that's kind of the point. Primitives aren't easy either. Even one thought to be secure yesterday might not be today, which makes it easy to get wrong merely by relying on literature from a year ago rather than today.
> The natural (and utterly impractical) line to draw is untrusted input.
I think you're right about that, both as to where the line really is and as to how impractical that is if you don't want to just end up with essentially everything being in scope.
> Compression is a tough one. I'd personally try padding.
I'm not sure you can fix it strictly in the lower layers. The general attack works like this: The attacker can supply some data, the victim compresses that data and some secret data together and then sends the combination encrypted over a channel where the attacker can observe the size. If the attacker-supplied data matches the secret data, it can be compressed more so it gets smaller.
The attacker's job is really easy if supplying one more byte of data that doesn't match the secrets causes the observed length to increase by one byte, but fixed padding just requires the attacker to find the padding boundary by supplying increasing amounts of pseudorandom (i.e. incompressible) data until the threshold for the next output size is reached, then swap in different bytes until some of them match the secret and it falls below that due to the compression. And random padding just requires more samples to account statistically for the randomness. In theory you might be able to fix it by making all messages the same length, but then if you want to support large messages, all messages become large, which could be unreasonably inefficient. And the whole point of the compression was to do the opposite of this.
The real solution is not compressing attacker-supplied data together with secret data to begin with, but that means the upper layer has to know not to do that.