NuGroom

Vulnerability Scanning

NuGroom checks packages against multiple vulnerability databases to surface known security advisories during scans. Vulnerability data is displayed in the console, included in exports, and embedded in SPDX SBOM output.


How It Works

NuGroom uses a two-tier approach to vulnerability detection:

Tier 1 — NuGet Feed Metadata (always active)

When NuGet resolution is enabled (--resolve-nuget, the default), the tool reads the vulnerability advisories embedded in the NuGet package metadata. This happens automatically as part of the existing feed resolution — no extra network calls are needed.

Each advisory includes:

Tier 2 — OSV.dev Database (enabled by default)

After NuGet resolution, the tool queries the OSV.dev open vulnerability database for all discovered package+version pairs. OSV.dev aggregates data from multiple sources including GitHub Advisory Database (GHSA) and the National Vulnerability Database (NVD).

Key characteristics:


Console Output

Vulnerabilities are displayed with severity-appropriate colors:

Severity Color
Critical Red
High Dark Red
Moderate Yellow
Low Gray

Example output:

  🚨 Severity: Critical [OSV] GHSA-abcd-1234 — Remote code execution — https://github.com/advisories/GHSA-abcd-1234
  🚨 Severity: Moderate — https://github.com/advisories/GHSA-efgh-5678

Entries from the NuGet feed show severity and advisory URL. Entries from OSV additionally show the advisory ID, summary, and source label [OSV].


Command Line Options

Option Description Default
--list-vulnerabilities Scan all packages for vulnerabilities and report only if any are found  
--skip-vuln Disable OSV.dev vulnerability database queries OSV enabled
--no-vuln-cache Disable local vulnerability result caching Cache enabled
--vuln-cache-path <path> Path for the vulnerability cache file .nugroom/vuln-cache.json
--export-vulnerabilities <path> Export vulnerability report to a separate file  

CLI flags override config file values. For example, --skip-vuln disables OSV even if the config file has "OsvEnabled": true.

Examples:

# Scan with OSV disabled (NuGet feed advisories still shown)
nugroom --config settings.json --skip-vuln

# Export vulnerability report as JSON
nugroom --config settings.json --export-vulnerabilities vuln-report.json

# Export as CSV
nugroom --config settings.json --export-vulnerabilities vuln-report.csv --export-format csv

# Use a custom cache path
nugroom --config settings.json --vuln-cache-path /tmp/vuln-cache.json

# Disable caching entirely
nugroom --config settings.json --no-vuln-cache

Vulnerability-Only Scan

Use --list-vulnerabilities to scan all packages and report only vulnerabilities — no updates, migrations, or other changes are made. This is useful for security audits and CI/CD pipeline gates.

The tool exits with code 0 if no vulnerabilities are found, or 1 if vulnerabilities are detected.

Examples:

# Check local projects for vulnerabilities
nugroom --paths ./src --list-vulnerabilities

# Check Azure DevOps repositories for vulnerabilities
nugroom --config settings.json --list-vulnerabilities

# Check and export a vulnerability report
nugroom --paths ./src --list-vulnerabilities --export-vulnerabilities vuln-report.json

# Use in a CI/CD pipeline gate (non-zero exit fails the step)
nugroom --config settings.json --list-vulnerabilities --export-vulnerabilities vuln-report.json --export-format csv

Console output when vulnerabilities are found:

Found 3 vulnerable package reference(s):

  Newtonsoft.Json (used: 12.0.3)
    🚨 Severity: High [OSV] GHSA-5crp-9r3c-p9vr — Improper handling of ...
    - MyApp / src/MyApp/MyApp.csproj (12.0.3)
    - MyLib / src/MyLib/MyLib.csproj (12.0.3)

Console output when no vulnerabilities are found:

No vulnerabilities found.

Caching

To avoid repeated network calls, OSV query results are cached locally in a JSON file. The cache is enabled by default and can be configured via the Vulnerability section in the config file.

Setting Default Description
CacheEnabled true Enable or disable the local vulnerability cache
CacheTtlHours 24 Time-to-live for cached entries in hours
CachePath .nugroom/vuln-cache.json File path for the cache (relative paths resolved from CWD)

Expired entries are automatically pruned when the cache is loaded and saved. The cache file is created on first use — no manual setup is needed.


Configuration

Add a Vulnerability section to your config file to customise behavior:

{
  "Vulnerability": {
    "OsvEnabled": true,
    "OsvBaseUrl": "https://api.osv.dev/v1/",
    "CacheEnabled": true,
    "CacheTtlHours": 24,
    "CachePath": ".nugroom/vuln-cache.json"
  }
}

Configuration Fields

Field Type Default Description
OsvEnabled bool true Query the OSV.dev database for known vulnerabilities
OsvBaseUrl string https://api.osv.dev/v1/ Base URL for the OSV API (override for self-hosted or proxy deployments)
CacheEnabled bool true Cache vulnerability query results to disk
CacheTtlHours int 24 Time-to-live for cached entries in hours (minimum 1)
CachePath string .nugroom/vuln-cache.json File path for the vulnerability cache

Disabling Vulnerability Scanning

To disable OSV.dev queries entirely (NuGet feed advisories are still shown):

{
  "Vulnerability": {
    "OsvEnabled": false
  }
}

Using a Proxy or Self-Hosted OSV Instance

Override the base URL if your environment requires routing through a proxy or uses a self-hosted OSV-compatible API:

{
  "Vulnerability": {
    "OsvBaseUrl": "https://osv-proxy.internal.corp/v1/"
  }
}

Exporting Vulnerability Reports

Use --export-vulnerabilities <path> or the ExportVulnerabilities config field to produce a standalone vulnerability report. The format is controlled by --export-format (default: JSON).

JSON Format

The JSON report groups vulnerabilities by package and includes affected projects:

{
  "generatedUtc": "2025-01-15T10:30:00Z",
  "totalVulnerabilities": 3,
  "packagesAffected": 2,
  "packages": [
    {
      "packageName": "Newtonsoft.Json",
      "latestVersion": "13.0.3",
      "usedVersions": ["12.0.3"],
      "advisories": [
        "Severity: High [OSV] GHSA-5crp-9r3c-p9vr — Improper handling of ...",
        "Severity: High — https://github.com/advisories/GHSA-5crp-9r3c-p9vr"
      ],
      "affectedProjects": [
        {
          "repository": "MyApp",
          "projectPath": "/src/MyApp/MyApp.csproj",
          "version": "12.0.3"
        }
      ]
    }
  ]
}

CSV Format

The CSV report has one row per advisory per package reference:

PackageName,Version,LatestVersion,Advisory
Newtonsoft.Json,12.0.3,13.0.3,"Severity: High [OSV] GHSA-5crp-9r3c-p9vr — ..."

SBOM Integration

When exporting an SPDX 3.0.0 SBOM (--export-sbom), vulnerability data is included in the security info section of each affected package element. Both NuGet feed advisories and OSV results are captured.


Data Sources

Source Coverage Auth Rate Limits
NuGet Feed Metadata Official NuGet.org advisories None (part of feed metadata) N/A (no extra calls)
OSV.dev Aggregates GHSA, NVD, and other databases None Generous; batch queries keep usage low

Architecture

NuGroom/Vulnerability/
  VulnerabilityRecord.cs       — Unified advisory model (Id, Severity, Summary, URL, Source, Aliases)
  IVulnerabilitySource.cs      — Interface for vulnerability data sources
  OsvVulnerabilitySource.cs    — OSV.dev batch API client
  VulnerabilityAggregator.cs   — Multi-source orchestrator with deduplication
  VulnerabilityCache.cs        — File-based cache with TTL expiration

The IVulnerabilitySource interface supports adding custom vulnerability sources in the future (e.g. local advisory files for air-gapped environments).


See also: Configuration · Features · Export Formats