Skip to content

bug: Java parser ignores groupId, so an internal artifact named core is reported as Drupal core, MobileIron Core and ONLYOFFICE core #5904

Description

@Eljees

Description

The pom.xml parser (cve_bin_tool/parsers/java.py) never reads <groupId>. It builds the purl as pkg:maven/<artifactId> and, when purl2cpe has nothing for that, falls back to find_vendor(), which returns every NVD vendor that has a product of that name.

For a private module whose artifactId happens to be core, that means the component is reported three times over, as drupal:core, mobileiron:core and onlyoffice:core, and inherits all of their CVEs.

To reproduce

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>ru.example.agent</groupId>
  <artifactId>core</artifactId>
  <version>3.29.3</version>
</project>

Hermetic probe (a stand-in cve_db that answers the way NVD does for the product name core):

import logging, pathlib, tempfile
from cve_bin_tool.parsers.java import JavaParser

class FakeDB:
    def get_vendor_product_pairs(self, product):
        return [{"vendor": v} for v in ("drupal", "mobileiron", "onlyoffice")] if product == "core" else []

p = JavaParser(FakeDB(), logging.getLogger("probe"), validate=False)
p.dbpath = pathlib.Path(tempfile.mkdtemp()) / "empty.db"
for si in p.run_checker("pom.xml"):
    print(si.product_info.vendor, si.product_info.product, si.product_info.version)

Output on main (b1d0905):

drupal core 3.29.3
mobileiron core 3.29.3
onlyoffice core 3.29.3

What it did in practice

This came out of a real scan of a vendor's Java delivery. Its modules are named <product>-core, <product>-broker and so on, with artifactId core under a private groupId. cve-bin-tool attributed 492 of its 534 findings to core 3.29.3-SNAPSHOT, among them every one of the 62 CRITICAL findings in the report -- for example CVE-2016-9450, a cache-poisoning bug in the Drupal 8 password-reset form, pinned on an in-house Java module. The report's verdict ("must not be deployed") rested entirely on this.

Why it is not caught today

  • run_checker calls self.generate_purl(product) without a namespace, so the purl carries no groupId and purl2cpe is queried with pkg:maven/core and pkg:maven/%/core -- the wildcard would even borrow another group's core.
  • find_vendor fans out to every vendor for the bare product name. That was a deliberate interim upgrade in Improve handling of multiple vendors in package parsers #2798 ("multiple vendors is an upgrade over the first one"), and @anthonyharrison anticipated there that a hint from the metadata would be needed to cut the false positives back. Improve handling of multiple vendors in package parsers #2798 was later closed as solved by the PURL integration -- but for Java the purl was being built without its namespace, so the fallback was still reached with no hint at all.

Maven already gives us that hint: the groupId is the vendor namespace.

Also

While at it: when a pom has a <parent>, the parser reports the parent's artifactId as the product and never reads the module's own. Every module of a multi-module build is recorded under the parent's name. artifactId is required and never inherited in Maven; only groupId and version are.

I have a fix with hermetic tests for both and will link the PR.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions