Yup. Here's a concrete example -- my team owns a couple of java services. They're spring boot with slf4j as our logging wrapper, using the default logging implementation of logback -- we didn't opt for log4j. So we're good, right? Well, let's do a `gradle dependencies` and see if we're pulling it in transitively -- still good. See some `log4j-api`, but no `log4j-core`. We're not actually doing any logging with log4j -- the "api" is from spring to allow you to use log4j if you want. Again, we're not, so we're fine.
Oh, but it does turn out that we do have the elastic apm agent, and it has log4j as a shaded dependency. So not as free and clear as we thought, and damn hard to detect that.
Shaded dependencies are a nightmare, and it's a particular bone I have to pick with using Elastic products that they think this practice is ok.
I prefer to package all my projects into a single fat jar, since it makes distribution so easy and clean, but if I was creating jar files with the expectation that other projects would use them I would make sure to package everything separately.
In this case using fat jars made things really easy to check for the effected classes and luckily for me I also didn't have any log4j-core classes in my fat jars.
log4j-api isn't actually a problem (directly). It's the usage of log4j-core that has the JndiManager class that's the injection point for RCE.
In the case of the transient dependency, it's further complicated because we've seen that some packages repackage the JARs they depend on... that means that statically analyzing for log4j is very difficult because you can't use hashes (even if you unzip the jar and hash class files directly).
I've been working on a scanner for this stuff on GitHub[0], and it's a real pain in the neck lol. Especially for Vendor software that you don't control.
Oh, but it does turn out that we do have the elastic apm agent, and it has log4j as a shaded dependency. So not as free and clear as we thought, and damn hard to detect that.