# How Trivy Scans Remote Git Repositories: Architecture and Implementation

> Learn how Trivy scans remote Git repositories. Discover its architecture, implementation details, and how it clones and analyzes source code for vulnerabilities.

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

---

**Trivy scans remote Git repositories by detecting URL targets, cloning them into temporary directories via `go-git`, and analyzing the source code with the same vulnerability and misconfiguration scanners used for local filesystems.**

Trivy's source repository scanning capability allows security teams to audit code directly from remote URLs without manual cloning. When you pass a Git URL to the `trivy repo` command, the tool automatically handles authentication, shallow cloning, and metadata extraction according to the aquasecurity/trivy source code. This workflow bridges remote version control with Trivy's vulnerability, misconfiguration, and secret detection engines.

## Target Detection and Artifact Initialization

When you execute `trivy repo <target>` with a URL-like string (e.g., `https://github.com/aquasecurity/trivy`), the CLI treats the input as a **remote Git repository**. The entry point in [`cmd/trivy/main.go`](https://github.com/aquasecurity/trivy/blob/main/cmd/trivy/main.go) routes the request to the artifact factory, which invokes `pkg/fanal/artifact/repo/git.NewArtifact` to create a specialized artifact.

In [`git.go`](https://github.com/aquasecurity/trivy/blob/main/git.go), the `NewArtifact` function sets `artifactOpt.Type = types.TypeRepository` and initializes the artifact with cloning capabilities. The factory first attempts to resolve the target as a local path, then falls back to the remote clone path if the target resembles a URL. This logic appears in [[`pkg/fanal/artifact/repo/git.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/fanal/artifact/repo/git.go) lines 27-34](https://github.com/aquasecurity/trivy/blob/main/pkg/fanal/artifact/repo/git.go#L27-L34).

## URL Normalization and Cloning Strategy

Before cloning, Trivy normalizes the target string through the `newURL` function to ensure a valid scheme is present. This allows shorthand inputs like `github.com/user/repo` to work correctly by prepending `https://` when needed, as implemented in [[`git.go`](https://github.com/aquasecurity/trivy/blob/main/git.go) lines 41-52](https://github.com/aquasecurity/trivy/blob/main/pkg/fanal/artifact/repo/git.go#L41-L52).

The `cloneRepo` function in [`git.go`](https://github.com/aquasecurity/trivy/blob/main/git.go) handles the actual repository acquisition:

- Creates a temporary directory using `xos.MkdirTemp`
- Performs a **shallow clone** with `Depth = 1` for performance unless a specific commit is requested
- Invokes the `go-git` library with options derived from CLI flags
- Checks out specific commits by performing a full clone first, then checking out the target SHA

This implementation spans [[`git.go`](https://github.com/aquasecurity/trivy/blob/main/git.go) lines 87-138](https://github.com/aquasecurity/trivy/blob/main/pkg/fanal/artifact/repo/git.go#L87-L138), where the clone configuration respects flags for branch, tag, and TLS verification.

## Authentication for Private Repositories

Trivy supports authenticated clones for private repositories through environment variables. The `gitAuth` function reads `GITHUB_TOKEN` or `GITLAB_TOKEN` from the environment and configures the `go-git` transport with the appropriate credentials. This enables scanning of private organizational codebases without embedding secrets in the command line, as defined in [[`git.go`](https://github.com/aquasecurity/trivy/blob/main/git.go) lines 55-81](https://github.com/aquasecurity/trivy/blob/main/pkg/fanal/artifact/repo/git.go#L55-L81).

## Metadata Extraction and Scanning

After cloning, Trivy hands the temporary directory to the generic local filesystem artifact logic in [`pkg/fanal/artifact/local/fs.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/fanal/artifact/local/fs.go). The `walker.FS` implementation extracts comprehensive Git metadata including **branch name**, **tags**, **commit SHA**, **author**, **committer**, and **commit message** during the inspection phase, as seen in [[`local/fs.go`](https://github.com/aquasecurity/trivy/blob/main/local/fs.go) lines 68-86](https://github.com/aquasecurity/trivy/blob/main/pkg/fanal/artifact/local/fs.go#L68-L86).

The `scan.Service.ScanArtifact` method in [`pkg/scan/service.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/scan/service.go) then:

1. Calls `artifact.Inspect` to gather file listings and metadata
2. Generates a stable `ArtifactID` by hashing the URL plus commit SHA (or path plus commit for local repos) via `generateArtifactID`
3. Forwards the artifact ID, name, and blob IDs to the backend scanners

This orchestration appears in [[`service.go`](https://github.com/aquasecurity/trivy/blob/main/service.go) lines 50-119](https://github.com/aquasecurity/trivy/blob/main/pkg/scan/service.go#L50-L119), with the ID generation logic specifically at [`lines 61-73`](https://github.com/aquasecurity/trivy/blob/main/pkg/scan/service.go#L61-L73). The final report embeds repository metadata under fields like `Metadata.RepoURL`, `Branch`, `Tags`, and `Commit`.

## CLI Options for Repository Scanning

The following command-line flags influence how Trivy interacts with remote repositories:

- **`--branch <name>`**: Clones only the specified branch using `ReferenceName` and `SingleBranch` options
- **`--tag <name>`**: Clones only the specified tag using the same mechanism as branch handling
- **`--commit <sha>`**: Performs a full clone and checks out the specific commit
- **`--insecure`**: Sets `InsecureSkipTLS` to skip TLS verification for HTTPS clones
- **`--no-progress`**: Suppresses clone progress output by setting `Progress` to `nil` (useful in CI environments)

These flags map directly to the `cloneRepo` configuration in [`git.go`](https://github.com/aquasecurity/trivy/blob/main/git.go), allowing precise control over the repository state being analyzed.

## Practical Usage Examples

Scan public repositories with shallow clones for maximum speed:

```bash
trivy repo https://github.com/aquasecurity/trivy

```

Target specific branches or tags to audit particular releases:

```bash
trivy repo https://github.com/aquasecurity/trivy --branch main
trivy repo https://github.com/aquasecurity/trivy --tag v0.45.0

```

Scan a precise commit for forensic analysis (requires full clone):

```bash
trivy repo https://github.com/aquasecurity/trivy --commit a1b2c3d4e5f6

```

Authenticate against private repositories using environment variables:

```bash
export GITHUB_TOKEN=ghp_XXXXXXXXXXXXXXXXXXXX
trivy repo https://github.com/yourorg/private-repo

```

Each command automatically clones the repository into a temporary directory, runs all enabled scanners (vulnerability, misconfiguration, secret, license), and produces a report containing the **RepoURL**, **Branch**, **Tags**, **Commit**, **CommitMsg**, **Author**, and **Committer** fields.

## Summary

- **Trivy detects remote Git URLs** automatically and routes them to `pkg/fanal/artifact/repo/git.NewArtifact` for specialized handling.
- **Shallow clones** (depth 1) are performed by default for performance, falling back to full clones only when specific commits are requested.
- **Authentication** leverages `GITHUB_TOKEN` or `GITLAB_TOKEN` environment variables via the `gitAuth` function for secure private repository access.
- **Metadata extraction** occurs through `walker.FS` in [`local/fs.go`](https://github.com/aquasecurity/trivy/blob/main/local/fs.go), capturing branch, tag, commit, and author information.
- **Stable artifact IDs** are generated by hashing the repository URL and commit SHA to uniquely identify scanned states.

## Frequently Asked Questions

### How does Trivy handle authentication for private Git repositories?

Trivy reads the `GITHUB_TOKEN` or `GITLAB_TOKEN` environment variables and passes them to the `go-git` transport layer via the `gitAuth` function in [`pkg/fanal/artifact/repo/git.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/fanal/artifact/repo/git.go). This allows authenticated HTTPS clones without exposing credentials in process lists or shell history.

### Can Trivy scan a specific commit instead of the latest branch?

Yes. When you specify `--commit <sha>`, Trivy performs a full clone (not shallow) and checks out the specific commit before scanning. This logic resides in the `cloneRepo` function where it detects the commit flag and adjusts the clone depth accordingly.

### Where does Trivy store the cloned repository during scanning?

Trivy creates a temporary directory using `xos.MkdirTemp` and clones the repository there. The directory is managed as part of the artifact lifecycle and is cleaned up after the scan completes, leaving no residual files on the host system.

### What metadata does Trivy include in reports for scanned repositories?

According to the `scan.Service` implementation in [`pkg/scan/service.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/scan/service.go), reports include `RepoURL`, `Branch`, `Tags`, `Commit`, `CommitMsg`, `Author`, and `Committer` fields. These are extracted during the inspection phase in [`pkg/fanal/artifact/local/fs.go`](https://github.com/aquasecurity/trivy/blob/main/pkg/fanal/artifact/local/fs.go) and embedded in the final vulnerability report.