Skip to content

User Guide Security Audit and SBOM

Leonard Ramminger edited this page May 10, 2026 · 3 revisions

Security, Audit, and SBOM

Prev: Configuration Reference | Up: User Guide | Next: Output and Report Formats

ReqPack adds shared security workflows on top of plugin-managed package operations. This page covers what audit input means, how exit codes work, and which settings actually change security behavior.

What Audit Targets Mean

  • rqp audit: audit installed packages across default systems.
  • rqp audit <system>: audit installed packages reported by that system.
  • rqp audit <system> <package> or scoped specs such as npm:react: audit explicit requested packages.
  • rqp audit . or rqp audit ./reqpack.lua: audit manifest contents.

Audit Basics

ReqPack can audit:

  • installed packages,
  • explicit package specifiers,
  • manifests,
  • whole ecosystems.

Examples:

rqp audit
rqp audit npm react
rqp audit npm:react maven:org.junit:junit
rqp audit .
rqp audit ./reqpack.lua
rqp audit --format cyclonedx-vex-json --output audit.json
rqp audit --format sarif --output audit.sarif

Exit-code behavior

  • without --output, rqp audit exits with 1 when findings exist,
  • with --output, export still succeeds and exits with 0.

This matters in CI. If you want both a file and a failing pipeline, check the exported results explicitly.

SBOM Basics

ReqPack can export inventory as table, JSON, or CycloneDX JSON.

rqp sbom
rqp sbom apt npm
rqp sbom --format json
rqp sbom --format cyclonedx-json --output sbom.json

Useful flags:

  • --wide
  • --no-wrap
  • --force
  • --sbom-skip-missing-packages

Key Security Settings

The most important config keys are:

security = {
  enabled = true,
  autoFetch = true,
  severityThreshold = "critical",
  scoreThreshold = 0.0,
  onUnsafe = "continue", -- continue | prompt | abort
  onUnresolvedVersion = "continue",
  strictEcosystemMapping = false,
  includeWithdrawnInReport = false,
  ignoreVulnerabilityIds = {},
  allowVulnerabilityIds = {},
  osvFeedUrl = "https://storage.googleapis.com/osv-vulnerabilities",
  osvRefreshMode = "manual", -- manual | periodic | always
  osvRefreshIntervalSeconds = 86400,
  osvDatabasePath = "~/.local/share/reqpack/security/osv",
}

CLI overrides exist for the same areas:

rqp install npm react --prompt-on-unsafe --severity-threshold high
rqp install npm react --abort-on-unsafe --score-threshold 7.5
rqp audit . --osv-feed ./test-data/osv --osv-refresh always
rqp audit . --ignore-vuln CVE-2024-0001 --allow-vuln GHSA-1234-5678

How ReqPack Decides Ecosystems

Audit quality depends on correct ecosystem mapping. ReqPack can get that mapping from plugin security metadata such as osvEcosystem, or from config via security.osvEcosystemMap / security.ecosystemMap.

Example:

security = {
  strictEcosystemMapping = true,
  osvEcosystemMap = {
    dnf = "RPM",
    maven = "Maven",
    npm = "npm",
  },
}

If you enable strictEcosystemMapping, missing mappings become hard failures instead of silent gaps.

How Security DBs And Plugins Work Together

ReqPack security flow has four parts:

  1. plugins describe security-relevant metadata,
  2. sync layer makes sure vulnerability DB has data for needed ecosystems,
  3. matcher resolves each package into ecosystem plus version-comparison rules,
  4. validator turns findings into continue/prompt/abort decision.

Plugin security metadata

Plugins can expose PluginSecurityMetadata. Most important fields for audit are:

  • osvEcosystem: maps plugin system such as dnf, maven, or npm to canonical OSV ecosystem
  • versionComparator: tells matcher how to compare package versions for that ecosystem
  • role: can mark plugin as normal package manager or security-provider
  • capabilities, ecosystemScopes, writeScopes, networkScopes, privilegeLevel: mostly trust and policy metadata

ReqPack uses metadata in several places:

  • validator and matcher prefer plugin osvEcosystem over config maps
  • sync service collects ecosystem scope from known plugins plus security.osvEcosystemMap
  • gateways can auto-discover plugins whose metadata role is security-provider

If plugin does not expose osvEcosystem, ReqPack falls back to security.ecosystemMap / security.osvEcosystemMap. If nothing maps system, matcher emits unsupported_ecosystem finding.

Vulnerability database layout

ReqPack stores advisory data in LMDB under security.osvDatabasePath.

Important storage facts from source:

  • LMDB directory is created on demand
  • advisories are indexed by advisory id, alias id, and ecosystem + normalized package name
  • sync state such as last_successful_sync_at, last_processed_modified, and ecosystem_scope is stored in same DB
  • when ReqPack works per ecosystem through gateway prep or matcher fallback, it may use per-ecosystem subdirectories under index path / OSV DB path

Relevant paths:

  • base OSV DB: security.osvDatabasePath
  • package index root: security.indexPath
  • if indexPath still default and osvDatabasePath changes, ReqPack aligns index root to OSV DB path

How sync works

Before validation, ReqPack may call sync layer to make sure advisory data exists.

High-level behavior:

  • autoFetch = false: validator only checks DB readiness, no automatic feed refresh
  • osvRefreshMode = manual with existing data: reuse local DB
  • osvRefreshMode = manual with empty DB and no explicit gateway scope: validator can continue without forcing initial download
  • periodic: refresh when last_successful_sync_at is older than osvRefreshIntervalSeconds
  • always: force refresh every time

Feed modes:

  • local path in osvFeedUrl: full import from filesystem tree
  • HTTP(S) feed in osvFeedUrl: full sync downloads <ecosystem>/all.zip or all.zip, delta sync uses modified_id.csv plus https://api.osv.dev/v1/vulns/<id>

Scope behavior:

  • sync service builds active ecosystem scope from explicit request, config maps, and plugin metadata
  • if ecosystem scope changes, ReqPack falls back from delta sync to full sync
  • overlay advisories from security.osvOverlayPath are loaded later by validator and merged into matching step, not into synced LMDB base feed

Gateways and backends

security.gateways and security.backends are indirection layer above raw OSV sync.

Current source-backed behavior:

  • if no gateways are configured, ReqPack uses security.defaultGateway
  • if no backend is configured or discovered, default backend is osv
  • configured gateway backend names are merged with discovered security-provider plugins
  • today only backend string osv has implementation
  • any other backend name currently yields low-severity sync_warning saying backend is not implemented yet

For osv backend, ReqPack can override from security.backends.osv:

  • feedUrl
  • refreshMode
  • refreshIntervalSeconds
  • overlayPath

Matching step

After sync, matcher processes packages from graph.

Order is:

  1. resolve ecosystem from plugin metadata or config map
  2. read version comparator from plugin metadata if available
  3. emit unresolved_version if package version is missing
  4. load advisories for ecosystem + package name from per-ecosystem DB or base DB
  5. merge overlay advisories from security.osvOverlayPath
  6. drop withdrawn advisories unless includeWithdrawnInReport = true
  7. emit vulnerability findings for matching advisories

Practical implication:

  • good plugin metadata improves both ecosystem mapping and version accuracy
  • feed DB provides baseline advisories
  • overlay path is best for local patches, temporary advisories, or deterministic tests

Validator disposition rules from source:

  • sync_error always blocks
  • unsupported_ecosystem blocks only when strictEcosystemMapping = true
  • unresolved_version blocks only when onUnresolvedVersion = "abort"
  • unresolved-version findings prompt when onUnresolvedVersion = "prompt"
  • other findings block or prompt based on severity, score, and onUnsafe / promptOnUnsafe
  • if prompting is required while interaction.interactive = false, ReqPack aborts

Testing Vulnerability Workflows Locally

This is the most useful setup when you are developing new plugins, audit rules, or CI workflows.

1. Point ReqPack at a local OSV data source

ReqPack accepts local filesystem paths as well as HTTP URLs for security.osvFeedUrl and --osv-feed.

rqp audit . --osv-feed ./test-data/osv --osv-refresh always

Or in config:

security = {
  osvFeedUrl = "./test-data/osv",
  osvRefreshMode = "always",
}

That lets you run deterministic audit tests without depending on the live upstream feed.

2. Use a dedicated local database path

rqp audit . --osv-db /tmp/reqpack-osv-dev --osv-refresh always

This avoids polluting your normal local vulnerability database while testing.

3. Test mapping failures on purpose

Use strictEcosystemMapping = true when bringing up a new plugin. That will expose missing osvEcosystem metadata or bad config mappings quickly.

4. Test unresolved-version behavior

If your plugin cannot reliably resolve versions yet, use:

rqp install myplugin foo --fail-on-unresolved-version

That forces you to fix resolvePackage() or package metadata before treating plugin's audit integration as production-ready.

5. Use allow/ignore lists for controlled experiments

security = {
  ignoreVulnerabilityIds = { "CVE-2024-1111" },
  allowVulnerabilityIds = { "GHSA-abcd-efgh" },
}

This is useful for tests, temporary waivers, or incremental rollout.

Local Development Config Example

return {
  interaction = {
    interactive = false,
  },
  security = {
    onUnsafe = "abort",
    onUnresolvedVersion = "abort",
    strictEcosystemMapping = true,
    severityThreshold = "high",
    osvFeedUrl = "./test-data/osv",
    osvDatabasePath = "/tmp/reqpack-osv-dev",
    osvRefreshMode = "always",
    osvEcosystemMap = {
      dnf = "RPM",
      maven = "Maven",
      npm = "npm",
    },
  },
}

SBOM Notes That Matter in Practice

  • sbom.defaultFormat and sbom.defaultOutputPath let you standardize local exports.
  • sbom.includeDependencyEdges controls whether dependency edges are included in JSON/CycloneDX output.
  • sbom.skipMissingPackages lets you keep exports going when some packages cannot be resolved.

Useful config example:

sbom = {
  defaultFormat = "cyclonedx-json",
  defaultOutputPath = "~/sbom.json",
  prettyPrint = true,
  includeDependencyEdges = true,
  skipMissingPackages = false,
}

Current exporter caveats:

  • sbom.defaultOutputPath is active
  • sbom.includeDependencyEdges is active
  • sbom.skipMissingPackages is active
  • sbom.prettyPrint is accepted by config and CLI override surface, but current exporter code does not read it
  • explicit versioned missing packages still fail even when skipMissingPackages = true

Practical Recommendations

  • Use explicit versions when you care about audit accuracy.
  • Implement or configure ecosystem mapping before trusting audit results.
  • Use table output locally, sarif or cyclonedx-vex-json in CI.
  • Treat --sbom-skip-missing-packages as a conscious trade-off, not a default.
  • Keep history.trackInstalled = true if you rely on snapshot-based reproducibility after audit/remediation work.

Related Pages

Prev: Configuration Reference | Up: User Guide | Next: Output and Report Formats

Clone this wiki locally