Back to blog

// OSSeva Blog

Compliance

Why Your Scanner Flags the ZooKeeper Inside a Product You Bought, and How VEX Attestation Answers It

Matt Reynolds8 min read

The short answer

Your scanner flags ZooKeeper because a product you bought ships its own copy of the ZooKeeper jar, and the scanner matches that jar's version against a vulnerability database. It does not test whether the vulnerability is exploitable in that product. A Vulnerability Exploitability eXchange (VEX) statement is the standard way to answer the finding: a machine-readable record that says, per CVE, whether the product is affected and why. A VEX attestation of not_affected is only credible when it carries evidence from the actual configuration.

Why the vulnerability scanner finds ZooKeeper at all

ZooKeeper is half runtime, half library. The ensemble is a server, but every product that talks to it ships the client jar, and many products also ship the server. Solr, HBase, Hive, Hadoop, NiFi, Kafka 3.x and the Cloudera and Hortonworks distributions all bundle a specific ZooKeeper version. Java products that use Apache Curator get ZooKeeper transitively, because Curator's client module declares ZooKeeper as a dependency. Many teams only learn they run ZooKeeper when the scan report arrives.

Scanners identify the component by fingerprinting the jar. Trivy, for example, reads the pom.properties and MANIFEST.MF files inside a JAR and, failing that, looks up the file's SHA-1 digest in its Java database. Once it has org.apache.zookeeper:zookeeper at a version, it lists every CVE whose affected range includes that version. So a product carrying ZooKeeper 3.6.4 is reported for CVE-2023-44981 whether or not SASL quorum authentication is ever switched on, and the vendor's product is flagged for the ZooKeeper inside it.

What VEX is

The Vulnerability Exploitability eXchange complements an SBOM. The SBOM says which software components a product contains; VEX says whether a given vulnerability affects the product. Three formats carry it:

  • OpenVEX defines four statuses: not_affected, affected, fixed and under_investigation. A not_affected statement must include a justification or an impact statement, and an affected statement must include an action statement.
  • CSAF 2.0 uses a VEX profile with the product statuses known_not_affected, known_affected, fixed and under_investigation.
  • CycloneDX records an analysis state per vulnerability, including not_affected, exploitable and resolved, with its own justifications such as requires_configuration.

OpenVEX and CSAF share five justifications for not affected: component_not_present, vulnerable_code_not_present, vulnerable_code_not_in_execute_path, vulnerable_code_cannot_be_controlled_by_adversary and inline_mitigations_already_exist.

How VEX is generated and consumed

A VEX document is normally produced by the product vendor, because the vendor knows how each component is used. It is published next to the SBOMs, which may be in CycloneDX or SPDX format, and it refers to components by an identifier such as a package URL. The consumer loads it into the scanner so the vulnerability status follows the analysis. Trivy, for example, accepts CycloneDX, OpenVEX and CSAF VEX files through its --vex option and filters out vulnerabilities marked not_affected or fixed.

The use cases are practical ones. Security teams stop repeating triage on the same false positives on every scan. Vulnerability management tools can automate the exploitability status of vulnerabilities across a software supply chain instead of relying on spreadsheets. Remediation effort goes to the vulnerable component that is actually exploitable. The limit of any VEX implementation is trust: a VEX document is only as good as the analysis behind it, which is why the evidence matters more than the format.

What a credible not_affected attestation contains

Security teams have learned to distrust a bare "not affected". A statement that survives an audit names the exact component and version, the CVE, the status, the justification and the evidence. Take CVE-2023-44981, the SASL quorum peer authentication bypass. The ZooKeeper advisory says it applies only when quorum.auth.enableSasl=true and that quorum peer authentication is not enabled by default. The attestation should show:

  1. The zoo.cfg or Java system properties from every server in the ensemble, with no quorum.auth.enableSasl=true.
  2. How the setting is controlled: a configuration management template, or a product that does not expose it.
  3. Network evidence that the quorum and election ports are reachable only by ensemble members, the mitigation the advisory itself names.
  4. Who made the statement, when, and what change would invalidate it, such as enabling SASL quorum authentication later.
{
  "@context": "https://openvex.dev/ns/v0.2.0",
  "@id": "https://example.com/vex/zookeeper-2026-09-29",
  "author": "Example Corp product security",
  "timestamp": "2026-09-29T00:00:00Z",
  "version": 1,
  "statements": [{
    "vulnerability": { "name": "CVE-2023-44981" },
    "products": [{ "@id": "pkg:maven/org.apache.zookeeper/zookeeper@3.6.4" }],
    "status": "not_affected",
    "justification": "vulnerable_code_not_in_execute_path",
    "impact_statement": "quorum.auth.enableSasl is not set on any server; quorum ports are firewalled to ensemble members."
  }]
}

Some CVEs cannot be attested away. CVE-2024-23944, where persistent watchers leak child paths without an ACL check, sits in core request handling on 3.6 and 3.7, and no configuration switch avoids it. Those findings need a fix.

Why auditors object to end-of-life components at all

Even with every CVE answered, an auditor may still raise the component. NIST SP 800-53 control SA-22, Unsupported System Components, requires organisations to replace components when support "is no longer available from the developer, vendor, or manufacturer", or to provide alternative sources of continued support, in-house or from external providers. The control's guidance names open-source value-added vendors among those providers. ZooKeeper 3.4 to 3.7 have no upstream support, so SA-22 is the reason a clean VEX file does not close the finding by itself; see SBOM and end-of-life components.

Three ways to close the finding

  1. The vendor upgrades ZooKeeper in its product. This is the cleanest answer and the slowest, and for products that are themselves end of life it may never come.
  2. A patched drop-in build replaces the jar with one carrying backported fixes, with the same configuration and logs.
  3. Attestation documents each CVE that does not apply, with evidence, for the ones where that is true.

A patched jar needs its own documentation. Its SHA-1 digest matches nothing in Maven Central, so hash lookup cannot identify it, and if its embedded metadata still says 3.6.4 the scanner will keep reporting the upstream CVEs as if nothing changed. Record it in the SBOM as a distinct component with its own version string and supplier, and publish VEX statements with status fixed for each backported CVE.

Where OSSeva fits

Most teams fix this at the product level: keep the Kafka, Solr or HBase estate supported, rather than "fix ZooKeeper" on its own. OSSeva's ZooKeeper extended support provides patched drop-in builds for 3.4, 3.5, 3.6 and 3.7, third-party written attestation for CVEs that do not apply to a given deployment, and migration planning to Raft-based coordination. The ZooKeeper hub lists products and the versions they embed, and the CDH and HDP page covers the distributions.

Frequently asked questions

Is VEX the same as an SBOM?

No. An SBOM lists components. VEX states, per vulnerability, whether a product is affected. Scanners that support VEX use it to suppress findings marked not affected.

Who should write the VEX statement?

Normally the product vendor, because it knows how the component is used. Where the supplier will not, a third party with access to the deployment's configuration can provide a written attestation.

Does a VEX attestation remove the need to patch?

For the CVEs it covers, it removes the need to act now. It does not satisfy SA-22 for an unsupported component, and it becomes invalid if the configuration it relies on changes.

Tags

VEXSBOMZooKeeperVulnerability ManagementAttestation

Ready to get your open source under control?

Talk to an OSSeva engineer about CVE coverage, compliance, and migration support for your stack.