aquasecurity/trivy
Scan service
Active contributors: knqyf263, DmitriyLewen, simar7
Purpose
pkg/scan/ is the orchestrator that ties together the artifact handler, the cache, the analyzers, the vulnerability database, and the misconfiguration/secret/license scanners into a single ScanArtifact call. Every command that produces a types.Report — image, fs, repo, vm, sbom, client — eventually calls into this service.
Directory layout
pkg/scan/
├── service.go # scan.Service + Backend interface
├── service_test.go
├── export_test.go
├── local/
│ ├── service.go # local.Service: standalone Backend
│ └── service_test.go
├── langpkg/ # language-package vulnerability scanner
├── ospkg/ # OS-package vulnerability scanner
└── utils/ # helpersKey abstractions
| Symbol | File | Purpose |
|---|---|---|
scan.Service |
pkg/scan/service.go |
Top-level orchestrator. Wraps a Backend and an artifact.Artifact. |
scan.Backend |
pkg/scan/service.go |
Interface implemented by local.Service (standalone) and pkg/rpc/client.NewClient (remote). |
local.Service |
pkg/scan/local/service.go |
Standalone backend. Owns the applier, vulnerability detection, and licensing/secret/misconfig coordination. |
langpkg.Scanner |
pkg/scan/langpkg/scanner.go |
Vulnerability detection for language ecosystems. |
ospkg.Scanner |
pkg/scan/ospkg/scanner.go |
Vulnerability detection for OS package families. |
applier.Applier |
pkg/fanal/applier/applier.go |
Combines per-layer blobs into one ArtifactDetail. |
vulnerability.Client |
pkg/vulnerability/vulnerability.go |
Reads vulnerability records from the Trivy DB. |
How ScanArtifact works
sequenceDiagram
participant Caller as artifact.Run
participant Svc as scan.Service
participant Art as artifact.Artifact
participant Backend as scan.Backend
participant Local as local.Service
participant Applier as applier.Applier
participant LangPkg as langpkg.Scanner
participant OSPkg as ospkg.Scanner
participant Cache as cache
Caller->>Svc: ScanArtifact(ctx, opts)
Svc->>Art: Inspect(ctx)
Art-->>Svc: artifact.Reference (blob keys)
Svc->>Backend: Scan(targetName, artifactID, blobKeys, opts)
Backend->>Local: Scan(...)
Local->>Applier: ApplyLayers(artifactID, blobKeys)
Applier->>Cache: GetBlob each key
Applier-->>Local: ArtifactDetail (merged)
Local->>OSPkg: Detect(family, packages)
Local->>LangPkg: Detect(applications)
Local-->>Backend: ScanResponse
Backend-->>Svc: ScanResponse
Svc->>Svc: assemble types.Report (fingerprint, metadata)
Svc-->>Caller: types.ReportThe service is intentionally thin: it delegates discovery to the artifact, runs the backend, and assembles the report. All the interesting work happens in local.Service (or on the server side if the backend is remote).
What local.Service does
pkg/scan/local/service.go is the heart of standalone scanning. Its Scan method:
- Calls the applier to merge per-layer blobs into a single
ArtifactDetail. - Decides whether OS detection succeeded; falls back to a synthetic OS family for OS-less artifacts.
- Runs OS-package vulnerability detection (
ospkg.Scanner) if there is an OS family with packages. - Runs language-package vulnerability detection (
langpkg.Scanner) for every detected application/lockfile. - Includes misconfiguration findings, secret findings, and license findings that the analyzers already attached to the blobs.
- Filters by severity and other report options.
- Returns a
ScanResponsewith the populatedResultsslice.
The _ "github.com/aquasecurity/trivy/pkg/fanal/analyzer/all" import in service.go is what registers every analyzer; the same import lives in pkg/fanal/handler/all for post-handlers.
Backend split
The Backend interface is the seam between standalone and client/server modes. Standalone:
backend := local.NewService(applier, osPkg, langPkg, vulnClient)
service := scan.NewService(backend, artifact)Client mode (in pkg/commands/artifact/scanner.go):
backend, _ := client.NewClient(...) // returns a scan.Backend
service := scan.NewService(backend, artifact)The artifact.Artifact always runs locally — only the post-inspection scan is delegated. This is what makes content-addressed blob upload effective: the client only needs to send blobs the server hasn't seen.
Vulnerability detection split
Two scanners share the work:
- OS package scanner (
pkg/scan/ospkg/scanner.go) — wrapspkg/detector/ospkg/which knows about Alpine, Amazon Linux, Debian, Ubuntu, Photon, RHEL, Oracle, Rocky/Alma, SUSE, etc. Each distro family has its ownpkg/detector/ospkg/<family>/. - Language package scanner (
pkg/scan/langpkg/scanner.go) — wrapspkg/detector/library/which knows about each language ecosystem (Maven, npm, pip, Go, RubyGems, Cargo, NuGet, Composer, Conan, etc.).
Both consult the Trivy DB via pkg/vulnerability/.
Integration points
- fanal — produces the
BlobInforecords this service consumes. - Cache —
applier.ApplyLayersreads blobs from here. - Database — vulnerability data source.
- RPC — when the backend is remote, this is the wire.
- VEX — applied by the runner after
ScanArtifactreturns.
Entry points for modification
- Add a new vulnerability source — extend
pkg/vulnerability/and the relevant detector underpkg/detector/. - Add a new finding kind to
Result— updatepkg/types/report.go, the renderers inpkg/report/, andpkg/rpc/convert.go. - Change report assembly —
scan.Service.ScanArtifactis the single place that builds the top-leveltypes.Report(artifact ID, metadata, BOM, fingerprints). - Change OS/language balance —
local.Service.Scancontrols when each scanner runs.
Key source files
| File | Purpose |
|---|---|
pkg/scan/service.go |
Top-level orchestrator + Backend interface. |
pkg/scan/local/service.go |
Standalone backend. |
pkg/scan/langpkg/scanner.go |
Language vulnerability scanner. |
pkg/scan/ospkg/scanner.go |
OS vulnerability scanner. |
pkg/types/scan.go |
ScanOptions, ScanResponse types. |
pkg/vulnerability/vulnerability.go |
DB query client. |
pkg/detector/ospkg/ |
Per-distro OS detectors. |
pkg/detector/library/ |
Per-language library detectors. |
pkg/fanal/applier/applier.go |
Layer merger. |
See also
- Vulnerability scanning — feature-level overview.
- Misconfiguration scanning — how IaC findings reach the report.
- Server — what runs on the other side of the RPC boundary.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.