CVE-2026-63328 Overview
CVE-2026-63328 is a path traversal vulnerability [CWE-22] in Trivy, an open-source security scanner maintained by Aqua Security. Versions prior to 0.72.0 fail to confine plugin names to the ~/.trivy/plugins directory when the plugin manager in pkg/plugin/manager.go constructs file paths from plugin manifest metadata.
An attacker who persuades a user to install or run a malicious plugin can write the manifest and plugin binary to arbitrary user-writable paths. Plugins distributed through the official Trivy plugin index are not affected. The issue is resolved in Trivy 0.72.0.
Critical Impact
Malicious Trivy plugins can write attacker-controlled files to arbitrary user-writable locations outside the plugin directory, enabling local code execution and configuration tampering.
Affected Products
- Aqua Security Trivy versions prior to 0.72.0
- Trivy plugin manager component (pkg/plugin/manager.go)
- Environments installing third-party plugins outside the official Trivy plugin index
Discovery Timeline
- 2026-08-18 - CVE-2026-63328 published to NVD
- 2026-08-18 - Last updated in NVD database
Technical Details for CVE-2026-63328
Vulnerability Analysis
Trivy supports a plugin system that stores third-party plugins under ~/.trivy/plugins. The plugin manager reads a manifest file for each plugin and derives on-disk paths from metadata fields provided by the plugin itself. Prior to version 0.72.0, the manager did not validate that resolved paths remained inside the plugin root.
A plugin manifest that includes traversal sequences such as ../ in the plugin name or output path causes the manager to write the manifest and plugin binary to locations outside ~/.trivy/plugins. The write happens with the privileges of the user running Trivy, which typically includes access to shell configuration files, SSH keys, and executable search paths.
The vulnerability requires user interaction: the victim must install or run the malicious plugin. Plugins fetched from the official Trivy plugin index are curated and are not affected.
Root Cause
The root cause is missing path confinement when the plugin manager joins user-controlled manifest metadata with the plugin root directory. Standard filepath.Join calls in Go do not prevent traversal sequences from escaping a base directory, and the plugin manager did not perform additional validation.
Attack Vector
Exploitation requires a local user to install or execute a malicious plugin, for example via trivy plugin install <url> pointing to an attacker-controlled repository. Once the plugin is loaded, the manifest metadata directs writes to attacker-chosen paths within the user's writable filesystem.
// Fix in pkg/commands/app.go - guarded plugin manager initialization
ctx := context.Background()
var commands []*cobra.Command
// Avoid creating the plugin directory on every run; nothing to load if it is absent.
if !plugin.DirExists() {
return nil
}
manager, err := plugin.NewManager()
if err != nil {
log.WarnContext(ctx, "Failed to initialize the plugin manager", log.Err(err))
return nil
}
defer manager.Close()
plugins, err := manager.LoadAll(ctx)
if err != nil {
log.DebugContext(ctx, "No plugins loaded")
return nil
}
// Source: https://github.com/aquasecurity/trivy/commit/d4213d7735c74e57f06c02ccb39ebca67abc7959
The patch also introduces a traversal-resistant Root type in pkg/x/os/root.go that wraps Go's os.Root API. The new type confines every name passed to its methods to the plugin directory, preventing manifests from escaping the intended base path.
package os
import (
"errors"
"io/fs"
"os"
"path/filepath"
"golang.org/x/xerrors"
)
// Root is a traversal-resistant handle to a directory. It embeds *os.Root,
// so every name passed to its methods is confined to the directory.
type Root struct {
*os.Root
}
// NewRoot creates dir (0700) if necessary and opens it as a Root.
func NewRoot(dir string) (*Root, error) {
if err := os.MkdirAll(dir, 0o700); err != nil {
return nil, xerrors.Errorf("failed to create directory %q: %w", dir, err)
}
root, err := os.OpenRoot(dir)
if err != nil {
return nil, xerrors.Errorf("failed to open root %q: %w", dir, err)
}
return &Root{Root: root}, nil
}
// Source: https://github.com/aquasecurity/trivy/commit/d4213d7735c74e57f06c02ccb39ebca67abc7959
Detection Methods for CVE-2026-63328
Indicators of Compromise
- Files written outside ~/.trivy/plugins with recent modification times correlated to Trivy plugin installation activity
- Plugin manifests (plugin.yaml) containing .. sequences or absolute paths in name, output, or artifact fields
- trivy plugin install invocations referencing untrusted Git repositories or HTTP URLs not listed in the official plugin index
- Unexpected modifications to shell startup files (~/.bashrc, ~/.zshrc), SSH configuration, or user-writable PATH directories following Trivy usage
Detection Strategies
- Monitor process execution for trivy plugin install and trivy plugin run commands and capture the plugin source argument
- Compare file writes performed by the Trivy process against the expected ~/.trivy/plugins root and alert on writes outside that scope
- Inspect installed plugin manifests for traversal patterns before allowing execution in CI or developer workstations
Monitoring Recommendations
- Enable filesystem auditing on user home directories to log file creation and modification by developer tooling
- Track the version of Trivy in use across build agents and endpoints, alerting on versions below 0.72.0
- Log outbound network calls to plugin source URLs to identify installation from unapproved locations
How to Mitigate CVE-2026-63328
Immediate Actions Required
- Upgrade Trivy to version 0.72.0 or later on all workstations, CI runners, and container images
- Audit ~/.trivy/plugins and adjacent directories for unexpected files written by previous plugin installations
- Restrict plugin installation to sources listed in the official Trivy plugin index and block ad-hoc URLs in CI policy
Patch Information
Aqua Security fixed CVE-2026-63328 in Trivy 0.72.0. The fix confines plugin file operations to the plugin root using a new traversal-resistant Root wrapper around Go's os.Root API. Details are available in the GitHub Security Advisory GHSA-8rc5-4fr6-64pw, the GitHub Release v0.72.0, and the remediation commit.
Workarounds
- Do not install Trivy plugins from untrusted sources until the upgrade is applied
- Run Trivy in an isolated container or unprivileged sandbox account so that any traversal writes are confined to a disposable filesystem
- Remove the ~/.trivy/plugins directory on shared systems where plugin usage is not required
# Upgrade Trivy to the fixed version and verify
brew upgrade aquasecurity/trivy/trivy # macOS (Homebrew)
# or
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v0.72.0
trivy --version # confirm 0.72.0 or later
# Inspect existing plugins for traversal patterns
grep -R "\.\." ~/.trivy/plugins 2>/dev/null
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.
