Skip to content

[FEATURE] Add Grype as an alternative/complementary vulnerability scanner to Trivy #50

@advaitpatel

Description

@advaitpatel

Feature Request

Add Grype (by Anchore) as an optional second vulnerability scanner alongside Trivy. Grype uses a different vulnerability database (Anchore Grype DB) and CVE matching algorithm, meaning it often finds vulnerabilities that Trivy misses and vice versa. Running both improves detection coverage — which is exactly what an OWASP security tool should do.

Why Grype?

Feature Trivy Grype
Vulnerability DB Trivy DB (GitHub) Grype DB (Anchore)
SBOM support Yes Yes (CycloneDX, SPDX)
False positive rate Medium Low
OS packages Yes Yes
Language packages Yes Yes
JSON output Yes Yes
License Apache 2.0 Apache 2.0

Cross-referencing both scanners increases confidence — a CVE flagged by both is very likely real.

Proposed CLI Integration

# Use Grype instead of Trivy
docksec Dockerfile -i myapp:latest --scanner grype

# Use both (default when both installed)
docksec Dockerfile -i myapp:latest --scanner all

# Use only Trivy (current default)
docksec Dockerfile -i myapp:latest --scanner trivy

Implementation Plan

1. `setup_external_tools.py` — add Grype installation

def install_grype():
    """Install Grype vulnerability scanner."""
    if platform.system() == "Darwin":
        subprocess.run(["brew", "install", "anchore/grype/grype"], check=True)
    elif platform.system() == "Linux":
        subprocess.run(
            ["curl", "-sSfL", "https://raw.githubusercontent.com/anchore/grype/main/install.sh"],
            # pipe to sh -s -- -b /usr/local/bin
        )

2. `docker_scanner.py` — add Grype scan method

def scan_image_grype(self, image_name: str) -> dict:
    """Scan a Docker image using Grype and return structured results."""
    result = subprocess.run(
        ["grype", image_name, "-o", "json", "--fail-on", "none"],
        capture_output=True, text=True, timeout=self.config.trivy_timeout
    )
    return self._parse_grype_output(result.stdout)

def _parse_grype_output(self, json_output: str) -> list[dict]:
    """Normalize Grype JSON output to DockSec's internal vulnerability format."""
    ...

3. Deduplication

When both Trivy and Grype are used, deduplicate by CVE ID and merge metadata:

def _deduplicate_vulnerabilities(self, trivy_vulns, grype_vulns):
    """Merge and deduplicate vulnerabilities from multiple scanners."""
    seen = {}
    for v in trivy_vulns + grype_vulns:
        cve_id = v["VulnerabilityID"]
        if cve_id not in seen:
            seen[cve_id] = v
        else:
            # Keep highest severity, add source tag
            seen[cve_id]["sources"] = seen[cve_id].get("sources", ["trivy"]) + ["grype"]
    return list(seen.values())

4. Report Enhancement

Add a "Scanner Coverage" section to reports showing which scanner found each CVE.

Acceptance Criteria

  • Grype added to `setup_external_tools.py` with macOS + Linux support
  • `--scanner {trivy,grype,all}` CLI flag added
  • Grype JSON output normalized to same internal format as Trivy
  • Deduplication merges results from both scanners without losing data
  • Reports indicate which scanner(s) found each vulnerability
  • Grype is optional — tool still works with just Trivy installed
  • Unit tests for `_parse_grype_output()` and `_deduplicate_vulnerabilities()`

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is needed

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions