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: AnalysisResultWhy 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
.wasmfile 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/PostAnalyzerinstances. - Scan service — post-scanner modules can run after the scan returns.
- Plugin system — sibling extension mechanism.
Entry points for modification
- Change host-function set —
pkg/module/module.go. Be conservative: every new function expands the trust surface. - Change serialization —
pkg/module/serialize/. Both sides (host and guest) must agree. - Change module discovery —
pkg/module/command.goandmodule.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
- Plugin system — unsandboxed alternative.
- fanal — what modules extend.
- Patterns and conventions — registration patterns shared with built-in analyzers.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.