Open-Source Wikis

/

Trivy

/

Systems

/

Module system

aquasecurity/trivy

Module system

Active contributors: knqyf263

Purpose

Trivy's module system loads sandboxed analyzers and post-scanners written as WebAssembly (WASM) modules. Where plugins are unsandboxed external binaries, modules run inside wazero — a pure-Go WebAssembly runtime — with deliberately restricted host-function access. This makes it possible to share custom analyzers safely (a corporate scan rule, for example) without trusting an arbitrary binary.

Directory layout

pkg/module/
├── module.go              # host runtime; wazero setup, function imports
├── module_test.go
├── api/                   # the host ↔ guest contract
├── command.go             # `trivy module` command implementation
├── memfs.go               # in-memory FS adapter for guest reads
├── memfs_test.go
├── serialize/             # WASM-friendly serialization shims
└── wasm/                  # placeholder (modules are external)

Key abstractions

Symbol File Purpose
module.Manager pkg/module/module.go Loads and dispatches WASM modules.
tapi.* pkg/module/api/ The host-side bindings exposed to guest modules (logging, fs reads, registration).
module.WASMModule pkg/module/module.go Per-module wrapper around a wazero api.Module.
serialize.* pkg/module/serialize/ Cross-language serialization helpers used over the WASM boundary.
command.go pkg/module/command.go trivy module install/list/uninstall implementation.

What modules can do

A module can implement either:

  • An analyzer — sees one file at a time, returns AnalysisResult. Same interface as a built-in analyzer.
  • A post-scanner — runs after the scan and can mutate the report (for example, to drop or annotate findings).

Modules register via host functions imported under the env namespace; the host side is configured in pkg/module/module.go. Logging is exposed as four functions (debug, info, warn, error) backed by pkg/log.

Lifecycle

sequenceDiagram
    participant CLI
    participant Mgr as module.Manager
    participant Wazero as wazero runtime
    participant Module as guest WASM
    participant Walker as fanal walker

    CLI->>Mgr: trivy module install <url>
    Mgr->>Mgr: download .wasm, validate, store
    CLI->>Mgr: scan command starts
    Mgr->>Wazero: instantiate runtime, import host fns
    Mgr->>Wazero: load each .wasm
    Mgr->>Module: register() — module declares analyzers
    Walker->>Mgr: AnalyzeFile(path, info, opener)
    Mgr->>Module: invoke guest analyze()
    Module-->>Mgr: AnalysisResult bytes
    Mgr-->>Walker: AnalysisResult

Why WASM and not plugins

  • Sandboxing — guest modules cannot reach the host filesystem or network unless the host explicitly imports a function for it.
  • Portability — one .wasm file works on Linux, macOS, Windows, ARM64, AMD64 without per-platform releases.
  • Language flexibility — modules can be written in Rust, AssemblyScript, Go (TinyGo), or any other language with a WASM target.

The trade-off is that modules cannot do everything a native plugin can (e.g., spawn subprocesses, talk to a Docker daemon). For those use cases, plugins are still the right fit.

Configuration

The trivy module command (pkg/module/command.go) installs, lists, and uninstalls modules. Module storage defaults to ~/.trivy/modules/; --module-dir overrides it. Modules are loaded automatically at scan time when pkg/module.NewManager(...) is called by the runner — gated by the --enable-modules flag (see pkg/flag/module_flags.go).

Memory and FS

pkg/module/memfs.go exposes a minimal in-memory FS to guest modules. Each guest can read files from a virtual filesystem the host populates, but cannot enumerate beyond what is provided. This is how the analyzer interface is preserved across the WASM boundary.

Integration points

  • fanal — modules register as additional Analyzer/PostAnalyzer instances.
  • Scan service — post-scanner modules can run after the scan returns.
  • Plugin system — sibling extension mechanism.

Entry points for modification

  • Change host-function setpkg/module/module.go. Be conservative: every new function expands the trust surface.
  • Change serializationpkg/module/serialize/. Both sides (host and guest) must agree.
  • Change module discoverypkg/module/command.go and module.NewManager.

Key source files

File Purpose
pkg/module/module.go Wazero runtime, host function imports, dispatch.
pkg/module/api/ Host ↔ guest contract types.
pkg/module/command.go trivy module command.
pkg/module/memfs.go In-memory FS for guest reads.
pkg/module/serialize/ Cross-language serialization.

See also

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Module system – Trivy wiki | Factory