stout
Article

Vulnerability Scanning for Installed Packages with stout audit

How stout audit checks your installed packages against CVE databases — and how to integrate it into your security workflow.

Neul Labs ·
#stout#security#vulnerability#cve#audit

Knowing what packages are installed on your system is the first step. Knowing which of those packages have known security vulnerabilities is what actually keeps your infrastructure safe. stout audit scans every installed package against aggregated CVE databases and reports vulnerabilities with severity ratings, affected version ranges, and remediation steps — in under a second, entirely offline.

The gap in Homebrew’s security model

Homebrew does not include a vulnerability scanner. If you want to know whether your installed version of openssl has a known CVE, you need to check external databases manually — cross-referencing brew list --versions output against the National Vulnerability Database (NVD), GitHub Security Advisories, or OSV. This is tedious for one package and impractical for the 50-200 packages a typical developer workstation has installed.

Some teams build ad-hoc scripts to automate this, but they are brittle: they depend on external API availability, require mapping Homebrew formula names to CPE identifiers, and cannot run in air-gapped environments.

How stout audit works

stout bundles vulnerability data directly into its SQLite index. During each stout update, the index build process aggregates vulnerability information from multiple sources:

  • National Vulnerability Database (NVD) — the authoritative US government CVE database
  • OSV (Open Source Vulnerabilities) — Google’s aggregated vulnerability database
  • GitHub Security Advisories (GHSA) — vulnerability reports from GitHub’s ecosystem

This data is stored in a dedicated table in the SQLite index:

CREATE TABLE vulnerabilities (
    id INTEGER PRIMARY KEY,
    cve_id TEXT NOT NULL,
    formula_name TEXT NOT NULL,
    affected_versions TEXT NOT NULL,   -- Version range expression
    fixed_version TEXT,                -- NULL if no fix available
    severity TEXT NOT NULL,            -- critical, high, medium, low
    cvss_score REAL,
    summary TEXT,
    references TEXT                    -- JSON array of URLs
);

CREATE INDEX idx_vuln_formula ON vulnerabilities(formula_name);

When you run stout audit, the command reads your installed packages from the local Cellar, then queries this table for any matching CVEs:

stout audit
# Scanning 147 installed packages...
#
# ⚠ openssl@3 3.1.4 — 2 vulnerabilities
#   CVE-2024-0727 (medium, CVSS 5.5) — PKCS12 decoding crash
#     Fixed in: 3.1.5
#   CVE-2023-6237 (low, CVSS 3.7) — Excessive time in RSA key check
#     Fixed in: 3.1.5
#
# ⚠ curl 8.4.0 — 1 vulnerability
#   CVE-2024-2004 (medium, CVSS 5.3) — HTTP/2 push headers memory leak
#     Fixed in: 8.6.0
#
# Scan complete: 147 packages, 3 vulnerabilities found
#   0 critical, 0 high, 2 medium, 1 low

The entire scan completes in under a second because it is a set of indexed SQLite queries against local data. No network requests are made.

Filtering and output formats

stout audit supports several filtering options to focus on what matters:

# Only show critical and high severity
stout audit --severity critical,high

# Audit a specific package
stout audit openssl@3

# JSON output for programmatic consumption
stout audit --format json

# Only show vulnerabilities with available fixes
stout audit --fixable

The JSON output is designed for integration with security tooling:

{
  "scan_time": "2026-03-22T10:15:00Z",
  "packages_scanned": 147,
  "vulnerabilities": [
    {
      "cve_id": "CVE-2024-0727",
      "formula": "openssl@3",
      "installed_version": "3.1.4",
      "fixed_version": "3.1.5",
      "severity": "medium",
      "cvss_score": 5.5,
      "summary": "PKCS12 decoding crash due to NULL pointer dereference",
      "references": [
        "https://nvd.nist.gov/vuln/detail/CVE-2024-0727",
        "https://www.openssl.org/news/secadv/20240125.txt"
      ]
    }
  ]
}

Automatic remediation

For vulnerabilities with available fixes, stout audit --fix will upgrade the affected packages:

stout audit --fix
# Scanning 147 installed packages...
#
# ⚠ openssl@3 3.1.4 — 2 vulnerabilities (fix available: 3.1.5)
# ⚠ curl 8.4.0 — 1 vulnerability (fix available: 8.6.0)
#
# Upgrading 2 packages to fix 3 vulnerabilities...
# Upgrading openssl@3 3.1.4 → 3.1.5
# Upgrading curl 8.4.0 → 8.6.0
#
# Done. Re-scanning...
# Scan complete: 147 packages, 0 vulnerabilities found

The --fix flag only upgrades packages that have known vulnerability fixes. It will not perform a blanket stout upgrade — it targets exactly the packages with security issues and upgrades them to the minimum version that resolves the reported CVEs.

CI/CD integration

stout audit is designed to run in CI pipelines as a security gate. The command exits with a non-zero exit code when vulnerabilities are found, and the threshold is configurable:

# Fail the pipeline on any critical or high vulnerability
stout audit --severity critical,high --exit-code

# In a GitHub Actions workflow:
# .github/workflows/security.yml
name: Security Audit
on:
  schedule:
    - cron: '0 9 * * 1'  # Every Monday at 9am
  workflow_dispatch:

jobs:
  audit:
    runs-on: macos-latest
    steps:
      - name: Install stout
        run: curl -fsSL https://stout.neullabs.com/install.sh | sh

      - name: Install project dependencies
        run: stout bundle install --file=Brewfile

      - name: Run security audit
        run: stout audit --severity critical,high --exit-code

      - name: Upload audit report
        if: always()
        run: stout audit --format json > audit-report.json

      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: security-audit
          path: audit-report.json

This workflow installs your project’s Homebrew dependencies, audits them for known vulnerabilities, and fails the build if any critical or high severity issues are found. The JSON report is uploaded as a build artifact for security team review.

Continuous monitoring with stout audit —watch

For long-lived environments like developer workstations or build servers, stout audit --watch monitors for newly disclosed vulnerabilities:

stout audit --watch
# Watching for new vulnerabilities...
# Index will be checked every 6 hours
# Press Ctrl+C to stop
#
# [2026-03-22 16:00] Index updated. No new vulnerabilities.
# [2026-03-22 22:00] Index updated. 1 new vulnerability:
#   CVE-2026-1234 (high) affects git 2.43.0 — fixed in 2.43.2

The watch mode runs as a background process and can be configured to send notifications via system notifications, webhook, or email when new vulnerabilities are discovered affecting your installed packages.

Version range matching

Vulnerability data often specifies complex affected version ranges. stout implements semantic version range matching that handles the nuances of how CVEs are reported:

  • Exact version: = 3.1.4
  • Range: >= 3.0.0, < 3.1.5
  • Multiple ranges: >= 3.0.0, < 3.0.14 || >= 3.1.0, < 3.1.5

stout parses these ranges and compares them against the exact version string installed on your system. This handles edge cases like packages with non-standard versioning schemes, revision bumps, and Homebrew-specific version suffixes.

Audit policies for teams

Organizations can define audit policies that standardize how vulnerabilities are handled across all developer machines:

# stout-audit-policy.toml
[policy]
max_severity = "medium"          # Block installs above this severity
grace_period_days = 30           # Days before a fixable vuln becomes blocking
require_fix_within_days = 7      # Days to apply fix after it's available
ignore_cves = [
    "CVE-2023-XXXX",            # Accepted risk, documented in JIRA-1234
]

[notifications]
webhook = "https://slack.example.com/hooks/security"

Apply the policy with:

stout audit --policy stout-audit-policy.toml

When a policy is active, stout install will refuse to install packages with vulnerabilities exceeding the max_severity threshold, and stout audit will check compliance with the grace period and fix-within timelines.

Comparing with standalone scanners

Tools like Trivy, Grype, and Snyk can scan for vulnerabilities in various contexts. stout audit is specifically optimized for Homebrew/stout packages:

Featurestout auditStandalone scanners
Homebrew package awarenessNativeRequires mapping
Offline operationYesVaries
Speed< 1s5-30s
Auto-fixYes (--fix)Usually no
InstallationIncluded in stoutSeparate install

stout audit is not a replacement for comprehensive vulnerability management platforms, but it fills the specific gap of knowing whether your Homebrew-installed packages are safe — instantly, offline, and integrated directly into your package management workflow.

Need Rust performance engineering or AI agent expertise?

Neul Labs — the team behind stout — consults on Rust development, performance optimization, CLI tool design, and AI agent infrastructure. We build fast, reliable systems that ship.