scan

package
v0.15.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 14, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package scan runs the detector over every object of a repository, or every file of a directory tree, and attributes what it finds to commits, paths and refs.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AnnotateLocal added in v0.2.0

func AnnotateLocal(results []Result, local map[string][]string)

AnnotateLocal marks every finding whose credential is also configured on this machine, given the sources per fingerprint.

func Describe

func Describe(r Result) string

Describe renders the stats of one result as a compact status line.

func Revoke added in v0.2.0

func Revoke(ctx context.Context, results []Result, tokens []Finding, registry *detect.Registry) (int, error)

Revoke asks each credential's provider to revoke it, checks each one again and records the outcome on every finding of that credential in results. It returns the number of credentials the providers confirmed dead. A provider that refuses is reported in the error; the other providers' credentials are still revoked and checked.

func SortFindings

func SortFindings(fs []Finding)

SortFindings orders active credentials first, then the ones nothing has rejected, then opaque material nothing can verify, then the rejected ones; within a group material that is usable as it is before passphrase-protected material, then by kind and fingerprint.

Types

type Finding

type Finding struct {
	// Provider names the issuer of the credential: GitHub, Slack.
	Provider    string      `json:"provider"`
	Kind        detect.Kind `json:"kind"`
	Fingerprint string      `json:"fingerprint"`
	Token       string      `json:"-"`
	// Secret is the companion material of a credential made of several
	// strings, when it was found next to the token; see detect.Token.Secret.
	Secret           string `json:"-"`
	Redacted         string `json:"token"`
	ChecksumVerified bool   `json:"checksum_verified"`
	// Attribution is what the credential's own shape says about its owner,
	// such as the workspace id in a Slack token; known without --verify.
	Attribution string `json:"attribution,omitempty"`
	// Encrypted marks passphrase-protected material, useless without a
	// passphrase that may or may not have leaked with it; see detect.Token.
	Encrypted bool `json:"encrypted,omitempty"`
	// Opaque marks secret material of no recognised shape, a plaintext
	// Kubernetes Secret, which nothing can verify; see detect.KindInfo.
	Opaque       bool                 `json:"opaque,omitempty"`
	Verification *detect.Verification `json:"verification,omitempty"`
	// Revocation records what happened when patty asked the provider to revoke the credential.
	Revocation Revocation `json:"revocation,omitempty"`
	// Local lists where the same token is configured on this machine.
	Local []string `json:"local,omitempty"`
	// Unlocks lists the files in the scanned repositories the credential
	// opens, when its provider correlates findings with the content around
	// them: the sops files encrypted to an age identity.
	Unlocks   []Unlock   `json:"unlocks,omitempty"`
	Locations []Location `json:"locations"`
	// Occurrences counts objects the token appears in, across all locations.
	Occurrences int `json:"occurrences"`
}

Finding is one distinct credential and everywhere it appears.

func Merge added in v0.2.0

func Merge(results []Result) []Finding

Merge groups the findings of all results by credential, so one that leaked into several repositories is one entry with every location and everything it unlocks. Active credentials come first.

func NewFinding added in v0.5.0

func NewFinding(registry *detect.Registry, tok detect.Token) *Finding

NewFinding starts the finding for a credential: provider, kind, fingerprint and redacted value, with no locations yet.

func Revocable added in v0.2.0

func Revocable(results []Result, registry *detect.Registry) []Finding

Revocable returns the distinct active credentials across results that their provider's revocation endpoint accepts, active ones first.

func (Finding) Active added in v0.2.0

func (f Finding) Active() bool

Active reports whether the provider confirmed the credential as live.

func (Finding) Detected added in v0.6.0

func (f Finding) Detected() detect.Token

Detected rebuilds the detect.Token a finding stands for.

func (Finding) Revoked added in v0.2.0

func (f Finding) Revoked() bool

Revoked reports whether the provider confirmed the credential as dead.

func (Finding) Unverifiable added in v0.6.0

func (f Finding) Unverifiable() bool

Unverifiable reports whether the credential cannot be checked against its provider, so no verdict about it will ever come.

type Location

type Location struct {
	Repo       string          `json:"repo"`
	Object     string          `json:"object"`
	ObjectType string          `json:"object_type"`
	Path       string          `json:"path,omitempty"`
	Line       int             `json:"line"`
	Commit     *gitrepo.Commit `json:"commit,omitempty"`
	// Refs contains the refs whose history includes the commit.
	Refs []string `json:"refs,omitempty"`
	// Orphaned is true when no ref reaches the commit anymore.
	Orphaned bool `json:"orphaned"`
	// Rewrite explains how the commit went unreachable on the server, when known.
	Rewrite string `json:"rewrite,omitempty"`
}

Location is one place a token was found.

type Options

type Options struct {
	// Workers is the number of parallel `git cat-file` readers.
	Workers int
	// MaxObject skips objects larger than this many bytes.
	MaxObject int64
	// Ignore holds the token fingerprints and credential kinds to leave out
	// of the results.
	Ignore map[string]bool
	// Providers is the set of credential providers to look for. It is
	// required: the caller assembles it, so this package need not know any
	// provider. A nil registry is a programming error and panics.
	Providers *detect.Registry
	// Verify checks each credential found against its provider's API.
	Verify bool
}

Options tune a repository scan.

type Remote added in v0.13.0

type Remote struct {
	Rewrites []Rewrite
	// Contributors are GitHub logins, as the repository's contributors
	// endpoint lists them; the scan adds the logins it reads from noreply
	// author addresses itself.
	Contributors []string
}

Remote is what the hosting service knows about a repository beyond its objects: the commits its activity feed reports as rewritten, and the logins of its contributors. A local repository has neither.

type Result

type Result struct {
	Target   string    `json:"target"`
	Findings []Finding `json:"findings"`
	Stats    Stats     `json:"stats"`
	Notes    []string  `json:"notes,omitempty"`
	// Files is true when the target is a file tree with no repository
	// behind it, a plain directory or a single file; its findings have no
	// history.
	Files   bool   `json:"files,omitempty"`
	Err     error  `json:"-"`
	Error   string `json:"error,omitempty"`
	Skipped bool   `json:"skipped,omitempty"`
}

Result is the outcome for one target.

func Dir added in v0.14.0

func Dir(ctx context.Context, name, root string, opts Options) (Result, error)

Dir scans every regular file below root as it is on disk, whether or not the tree is a repository, so the files a repository scan never sees are covered: an untracked .env, a credentials file copied into a project folder. A single file as root is scanned on its own. Symbolic links are not followed; .git directories, devices, sockets and pipes are left out; files larger than opts.MaxObject are skipped and counted. .gitignore is deliberately not honoured, since ignored files are where credentials hide. A finding's path is relative to root and it has no commit.

func Repo

func Repo(ctx context.Context, name string, repo *gitrepo.Repo, remote Remote, opts Options) (Result, error)

Repo scans every blob, commit and tag object of the repository and attributes findings. remote annotates commits fetched by SHA and names the repository's contributors.

func Run

func Run(ctx context.Context, targets []source.Target, opts RunOptions, onResult func(Result)) []Result

Run scans all targets and calls onResult as each completes, one call at a time. Results are returned in target order.

type Revocation added in v0.2.0

type Revocation string

Revocation is the outcome of asking a provider to revoke a credential.

const (
	// RevocationDone means the provider accepted the request and no longer honours the credential.
	RevocationDone Revocation = "revoked"
	// RevocationPending means the provider accepted the request but still
	// answered the follow-up check as active; GitHub processes revocations
	// asynchronously.
	RevocationPending Revocation = "pending"
	// RevocationUnsupported means the credential family cannot be revoked through the API.
	RevocationUnsupported Revocation = "unsupported"
)

type Rewrite

type Rewrite struct {
	SHA         string
	Description string
}

Rewrite names a commit that was fetched by SHA because a server-side ref update (force push, branch deletion) had made it unreachable.

type RunOptions

type RunOptions struct {
	Options
	// Cache holds the mirrors of GitHub targets.
	Cache *disk.Cache
	// Keep leaves mirrors in the cache after the scan for faster re-runs.
	Keep bool
	// Auth is used for HTTPS clones; nil for anonymous.
	Auth *gitrepo.Auth
	// GitHub is needed for the activity feed; nil disables it.
	GitHub *github.Client
	// Rewrites fetches commits the activity feed reports as force-pushed or deleted.
	Rewrites bool
	// ActivityPages caps the activity feed pages read per type and repository.
	ActivityPages int
	// Parallel is the number of repositories processed at once.
	Parallel int
	// Progress receives phase messages; may be nil.
	Progress func(target, msg string)
}

RunOptions configure a run over many targets.

type Stats

type Stats struct {
	Objects     int           `json:"objects"`
	Scanned     int           `json:"scanned"`
	Skipped     int           `json:"skipped_large"`
	Bytes       int64         `json:"bytes"`
	Refs        int           `json:"refs"`
	Orphaned    int           `json:"orphaned_commits"`
	Rewrites    int           `json:"rewrites_fetched"`
	Unavailable int           `json:"rewrites_unavailable"`
	Disk        int64         `json:"disk_bytes,omitempty"`
	Duration    time.Duration `json:"-"`
}

Stats summarises one repository scan.

type Summary

type Summary struct {
	// Repos counts every target, repository or not; Files the ones scanned
	// as files on disk only.
	Repos    int
	Files    int
	Failed   int
	Skipped  int
	Tokens   int
	Active   int
	Bytes    int64
	Objects  int
	Duration time.Duration
}

Summary aggregates results for the final line of a report.

func Summarize

func Summarize(results []Result) Summary

Summarize computes totals; tokens seen in several repositories count once.

type Unlock added in v0.7.0

type Unlock struct {
	Repo string `json:"repo"`
	Path string `json:"path"`
	// Detail is what the file says about the credential when the path
	// alone does not: the names and expiry of the certificate a private
	// key belongs to.
	Detail string `json:"detail,omitempty"`
}

Unlock is one file a credential opens or that names it; see Finding.Unlocks.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL