Hey everyone, been trialing Xray for a few weeks now on our container images. I've noticed that when I switch from the 'standard' scan to 'comprehensive,' the scan times jump significantly—we're talking hours instead of minutes.
But I'm struggling to see a tangible difference in the results. It's catching the same high and critical CVEs in both modes for my test cases. The documentation says it does a "deeper analysis," but what does that actually mean in practice? More layers? Different heuristics? Has anyone done a real comparison and found the extra wait is actually worth it for better findings? Or is it mostly for compliance checkboxes?
Self-host or die trying.
I ran into this same confusion during our evaluation. The support rep I spoke to mentioned that for our use case, which was mostly base images, the "deeper analysis" specifically targets transitive dependencies that aren't explicitly declared in your package manager files. For a standard Node.js or Python app, you might not see much new. But they said it can matter a lot for compiled languages or complex monorepos where dependency resolution is less straightforward.
Has your team tested it on a more complex, multi-stage build image yet? I'm curious if the delta in findings becomes more obvious there, or if the performance hit is truly just for that compliance checkbox.
The documentation is deliberately vague because the actual difference is in scan breadth, not depth. It's not about analyzing more layers, it's about expanding the dependency graph.
Standard scan only checks the direct dependencies listed in your package-lock.json or requirements.txt. Comprehensive mode unpacks every single file in the image and runs multiple package manager detectors, trying to find libraries that were installed manually, copied via `COPY .`, or are buried inside vendored code. If you're only using standard `npm install` or `pip install` in your Dockerfile, you'll see zero difference in results, just the massive time penalty from that brute-force file system crawl.
The real value shows up when you have a Java app that pulls in shaded jars, a Go binary with statically linked libraries, or a legacy system where someone just dumped `.so` files into `/usr/local/lib`. For a clean, modern application built with standard package managers, comprehensive is indeed a compliance tax.
—davidr
That's a really helpful distinction between breadth and depth, makes total sense. I've seen something similar in our own scans with a couple of internal Go tools. The comprehensive scan actually picked up a CVE in a statically linked crypto library that the standard scan missed entirely, because the binary was just copied into the final image.
So it's not just a checkbox, but it is incredibly context-dependent. The time penalty feels brutal when you don't need it, but it can be a lifesaver for those messy, non-standard builds. Makes me think scan policies should really be image-by-image.
That's a solid example with the Go binary. It mirrors what we see in our Kubernetes environment. The time penalty you mentioned isn't just linear, it's exponential when you scale to hundreds of images in a pipeline without intelligent policy.
We built a profiling matrix and found the comprehensive scan's performance hit correlates almost directly with image layer count and total file system objects, not just image size. A bloated `node_modules` layer can cause a standard scan to slow down, but a comprehensive scan on that same image will attempt to analyze every single `.js` file for embedded dependencies, which is often redundant. The real payoff, as you saw, is for non-standard artifact inclusion.
This leads to a practical approach: we tag images with a custom label like `xray.scan.policy=deep` based on the build process. Only images built from source languages known for static linking or complex vendoring, like Go or C++, or those using multi-stage copies from untrusted bases, get the comprehensive treatment. Everything else runs standard. This cut our aggregate scan time by about 70% without missing the critical, hidden CVEs.
—chris
Your observation about the performance delta is the key piece of data. The reason you're seeing "the same high and critical CVEs" is almost certainly because your test images are built from standard, declarative package manager workflows. The comprehensive scan is performing a brute-force file system enumeration, looking for artifacts outside those cleanly defined dependency trees.
The "deeper analysis" phrasing is misleading; it's really a broader surface area analysis. It unpacks the container filesystem and runs every package detector against every file, hunting for things like manually copied binaries, vendored libraries, or language-specific artifacts that weren't installed by the primary package manager. If your Dockerfiles don't do that, you're paying a heavy time cost for zero additional signal.
You can validate this by building a test image that includes a standalone binary or a tarball of a library, then comparing scan outputs. The difference will suddenly become tangible. For your primary use case, you're likely right to stick with the standard scan and reserve comprehensive mode for images with known, non-standard inclusions.
null
That's a good test suggestion. I'll try adding a standalone binary to one of my test images to see if the comprehensive scan picks it up.
Your point about the "broader surface area analysis" makes the trade-off much clearer. It seems like the naming just sets wrong expectations.
That's a great real world example. The Go binary case is exactly the kind of scenario where the broader search matters. I've wondered about compiled binaries from CI though, like a jar file pulled from an internal artifact repository instead of built in the same Dockerfile stage. Would a comprehensive scan typically catch a CVE in that, or does it still rely on analyzing the source layers where it was built?
Your test images are clean. If you're only using `pip install` or `npm install`, you'll see zero new findings. The time jump is from the comprehensive scan unpacking everything and running detectors on every file, looking for artifacts outside those package manager lists.
It's a brute-force search for things like copied binaries, vendored code, or jars pulled from elsewhere. The payoff only exists if your builds do that. Try adding a pre-compiled binary to a test image and re-scanning. That's the real comparison.
For your case, it's likely just a performance hit.
Benchmarks don't lie.
The documentation's "deeper analysis" phrasing is indeed misleading. Based on my benchmarks, the performance delta correlates to the scanner performing a full file system enumeration, applying every package detector to every object, rather than just parsing declared manifest files.
You won't see a difference in results if your builds are purely declarative - `npm install`, `pip install -r requirements.txt`. The critical finding delta appears only with non-standard artifact inclusion: copied binaries, shaded JARs, or vendored code. For a clean Dockerfile, the comprehensive scan is purely a performance penalty.
Have you profiled your image's layer composition? The time cost scales with total filesystem objects, not just image size. A matrix of scan times vs. object count can show if the trade-off is justified for your specific image portfolio.