# Trivy Rootfs vs Filesystem: Understanding the Difference Between Scan Targets

> Confused by Trivy rootfs vs filesystem scan targets? Learn when to scan OS packages with rootfs and source code/configs with filesystem for effective vulnerability detection.

- Repository: [Aqua Security/trivy](https://github.com/aquasecurity/trivy)
- Tags: deep-dive
- Published: 2026-03-23

---

**Use `trivy rootfs` when scanning an unpacked Linux root filesystem (like a container's rootfs or host `/`) for OS package vulnerabilities, and use `trivy filesystem` (or `trivy fs`) when scanning regular project directories containing source code, configuration files, or build artifacts.**

The aquasecurity/trivy vulnerability scanner provides two distinct modes for analyzing local directories: `rootfs` and `filesystem`. While both commands inspect directory contents, they differ fundamentally in their assumptions about the target structure and optimization strategies. Understanding the difference between Trivy's rootfs and filesystem scan targets ensures you select the appropriate command for container security scans versus traditional software composition analysis.

## Core Architectural Differences

### Target Kind Constants

In [`pkg/commands/artifact/run.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/commands/artifact/run.go), Trivy defines two distinct target type constants that determine scan behavior:

- **`TargetRootfs`** (`"rootfs"`) – Indicates the target is a complete Linux root filesystem
- **`TargetFilesystem`** (`"fs"`) – Indicates the target is a generic directory or project folder

These constants drive the initialization logic at lines 49-55, where the scanner determines whether to apply rootfs-specific optimizations or standard directory traversal.

### Command Implementation

The CLI commands are implemented separately in [`pkg/commands/app.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/commands/app.go) to handle distinct flag sets and initialization paths:

- **`NewRootfsCommand`** (lines 404-429) – Creates the `rootfs` subcommand with dedicated `rootfsFlags` and invokes `artifact.Run(..., artifact.TargetRootfs)`
- **`NewFilesystemCommand`** (lines 330-360) – Creates the `fs` subcommand with `fsFlags` and invokes `artifact.Run(..., artifact.TargetFilesystem)`

This separation ensures that each mode receives appropriate default configurations and help text tailored to its intended use case.

### Walker Behavior and File Analysis

The critical difference lies in [`pkg/fanal/walker/fs.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/fanal/walker/fs.go), where the **rootfs walker** expects a real Linux root layout (e.g., `/etc/os-release`, `/var/lib/dpkg`, `/var/lib/rpm`). When scanning only OS packages (`--scanners vuln --pkg-types os`), this walker reads package database files directly without traversing the entire directory tree.

Conversely, the **generic filesystem walker** used by `trivy fs` walks every file under the supplied path to locate language-specific lock files, secrets, and configuration files. This comprehensive traversal is necessary because the locations of these artifacts are unknown and distributed throughout the project structure.

## Performance Characteristics

### Rootfs Optimization for OS Packages

When executing `trivy rootfs --scanners vuln --pkg-types os /path/to/rootfs`, Trivy leverages the rootfs structure to bypass full filesystem traversal. The scanner directly accesses the OS package manifests (such as RPM or DPKG databases) and `os-release` files, significantly reducing scan time for large root filesystems.

This optimization is documented in the rootfs scanning guide and relies on the assumption that the directory mimics a standard Linux root layout.

### Filesystem Traversal Requirements

For `trivy filesystem`, Trivy must walk the entire directory tree because language packages (Node.js, Python, Go), secrets, and misconfigurations can reside anywhere within the project hierarchy. The generic walker cannot assume standard paths and performs comprehensive file discovery unless explicitly restricted with `--skip-dirs`.

## When to Use Each Scan Target

### Use `trivy rootfs` for:

- Scanning host machines at `/` or exported container rootfs directories
- Analyzing filesystems extracted via `docker export` or `podman export`
- Fast OS-package vulnerability detection where Linux distribution databases are present
- Security assessments of base images or operating system installations

### Use `trivy filesystem` for:

- Source code repositories and application projects
- CI/CD pipelines requiring language-specific dependency analysis
- Secret detection in configuration files or commit histories
- Misconfiguration scanning in infrastructure-as-code files
- Build artifact directories containing multiple project types

## Practical Code Examples

### Scanning an Exported Container Rootfs

Export a container's root filesystem and analyze it using the rootfs target:

```bash
docker export $(docker create alpine:3.10.2) | tar -C /tmp/rootfs -xvf -
trivy rootfs /tmp/rootfs

```

This command invokes `NewRootfsCommand` → `artifact.Run(..., artifact.TargetRootfs)`, treating `/tmp/rootfs` as a Linux root filesystem.

### Scanning a Project Directory

Analyze a Python application for vulnerabilities, secrets, and licenses:

```bash
trivy fs /home/user/my-python-app

```

This executes `NewFilesystemCommand` → `artifact.Run(..., artifact.TargetFilesystem)`, walking the entire directory tree to discover [`requirements.txt`](https://github.com/aquasecurity/trivy/blob/main/requirements.txt), `Pipfile.lock`, and configuration files.

### Optimized OS Package Scanning

Perform a fast scan of the host OS without full filesystem traversal:

```bash
trivy rootfs --scanners vuln --pkg-types os /

```

According to the Trivy source code in [`pkg/fanal/walker/fs.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/fanal/walker/fs.go), this command reads `/etc/os-release` and package databases directly, skipping the expensive directory walk required for language-specific analysis.

## Summary

- **`trivy rootfs`** assumes a Linux root filesystem structure and optimizes for OS package scanning by reading distribution databases directly rather than walking every file.
- **`trivy filesystem`** treats the target as a generic project directory and performs comprehensive traversal to detect language packages, secrets, and misconfigurations distributed throughout the tree.
- Both commands are defined in [`pkg/commands/app.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/commands/app.go) with separate initialization paths (`NewRootfsCommand` vs `NewFilesystemCommand`) and target constants (`TargetRootfs` vs `TargetFilesystem`).
- Choose `rootfs` for container/host filesystem analysis and `filesystem` for application source code and artifact scanning.

## Frequently Asked Questions

### Can I use `trivy filesystem` to scan a container rootfs?

Yes, but it will perform significantly slower for OS package detection. When you run `trivy fs` on an unpacked rootfs, the generic walker traverses every file rather than reading package databases directly. Use `trivy rootfs` specifically for rootfs targets to leverage the performance optimizations implemented in [`pkg/fanal/walker/fs.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/fanal/walker/fs.go).

### Why is `trivy rootfs` faster for OS package scanning?

The rootfs walker in Trivy's source code recognizes standard Linux paths like `/var/lib/dpkg` and `/var/lib/rpm`. When scanning with `--pkg-types os`, it accesses these databases directly without traversing the entire directory tree, while `trivy filesystem` must walk every directory to locate potential artifacts.

### Which command should I use in CI/CD pipelines?

Use `trivy filesystem` (or `trivy fs`) for CI/CD pipelines analyzing application source code, dependencies, and infrastructure configurations. Use `trivy rootfs` only when your pipeline exports and scans container root filesystems or base images as part of the security workflow.

### Do both commands support the same vulnerability scanners?

Both commands support vulnerability scanning, secret detection, and misconfiguration checks, but the discovery mechanism differs. The `filesystem` command is better suited for language-specific scanners that require `go.mod`, [`package-lock.json`](https://github.com/aquasecurity/trivy/blob/main/package-lock.json), or similar files, while `rootfs` excels at OS-level vulnerability detection through direct package manager database access.