detect

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Sep 12, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package detect finds credentials in arbitrary byte content and knows, per provider, how to verify and revoke them.

The scan is built for throughput: every provider does a handful of SIMD-accelerated substring searches for its fixed token prefixes followed by an exact shape check and, where the format allows it, an offline checksum. A well-formed string with a wrong checksum is not a token; that single check removes the false positives a regex scanner has to live with.

The shared vocabulary lives here: Kind, Token, Verification and the Provider interface. The providers themselves are sub-packages, assembled into a Registry by package providers.

Index

Constants

View Source
const UserAgent = "patty"

UserAgent identifies patty to the provider APIs.

Variables

This section is empty.

Functions

func All added in v0.5.0

func All(b []byte, ok func(byte) bool) bool

All reports whether every byte of b satisfies ok. The empty slice does.

func AlnumAt added in v0.5.0

func AlnumAt(content []byte, i int) bool

AlnumAt reports whether content has an alphanumeric byte at i; false past the end. Used to reject candidates that continue into a longer word.

func Do added in v0.5.0

func Do(client *http.Client, req *http.Request) (*http.Response, error)

Do sends the request with patty's User-Agent set.

func Fingerprint

func Fingerprint(value string) string

Fingerprint returns the fingerprint of a raw token value.

func IsAlnum added in v0.5.0

func IsAlnum(c byte) bool

IsAlnum reports whether c is an ASCII letter or digit.

func IsDigit added in v0.5.0

func IsDigit(c byte) bool

IsDigit reports whether c is an ASCII digit.

func IsHex added in v0.5.0

func IsHex(c byte) bool

IsHex reports whether c is a lower- or upper-case hexadecimal digit.

func ReadBody added in v0.5.0

func ReadBody(r io.Reader, limit int64) []byte

ReadBody reads at most limit bytes of a response body.

func Redact

func Redact(value string) string

Redact hides the middle of a credential, keeping enough of both ends to recognise it (`ghp_AbCd…WxYz`). A URL keeps its path up to the last segment, which is the secret part of a webhook (`https://…/T…/B…/Ab…Yz`).

func Span added in v0.5.0

func Span(content []byte, start, limit int, ok func(byte) bool) int

Span returns the length of the run of bytes starting at content[start] that satisfy ok, at most limit bytes.

Types

type DryRunRevoker added in v0.5.0

type DryRunRevoker interface {
	DryRunRevoke(ctx context.Context, token string) error
}

DryRunRevoker is a Provider whose revocation endpoint can rehearse a revocation: it answers as it would for the real request without revoking anything. patty uses it to preview a revocation before asking for confirmation.

type Kind

type Kind string

Kind names one credential family of one provider, such as a classic GitHub personal access token or a Slack bot token.

type KindInfo added in v0.5.0

type KindInfo struct {
	Kind Kind
	// Description is the human name: "personal access token (classic)".
	Description string
	// Revocable reports whether the provider's revocation endpoint accepts this kind.
	Revocable bool
	// RevokePage is where the owner revokes a credential of this kind by hand.
	RevokePage string
	// RevokeNote is added to the manual revocation advice when the API cannot
	// revoke the kind: what to check instead, or why it does not matter.
	RevokeNote string
	// RevokeEffect names a side effect of revoking through the API that is
	// easy to miss. The placeholder {app} stands for the issuing application.
	RevokeEffect string
}

KindInfo describes one credential family.

type LocalSources added in v0.5.0

type LocalSources struct {
	// Env lists environment variables tools read the credential from.
	Env []string
	// ConfigFiles are relative to the XDG config directory (~/.config).
	ConfigFiles []string
	// HomeFiles are relative to the home directory.
	HomeFiles []string
	// Commands print a credential to stdout, such as `gh auth token`.
	Commands [][]string
}

LocalSources names where a provider's credentials are configured on the machine running patty. Paths may contain globs.

type Provider added in v0.5.0

type Provider interface {
	// Name is how the provider is called in reports: "GitHub", "Slack".
	Name() string
	// Kinds describes every credential family the provider detects.
	Kinds() []KindInfo
	// Find returns every credential of this provider in content. Offsets
	// are set; line numbers are filled in by the Registry.
	Find(content []byte) []Token
	// Verify asks the provider whether the credential is still accepted.
	// Only the provider's explicit invalid-credentials answer is reported as
	// revoked; anything else that is not a clean acceptance is unknown.
	Verify(ctx context.Context, tok Token) Verification
	// Revoke asks the provider to revoke the given credential values. A nil
	// error means every request was accepted; the caller confirms the
	// outcome with Verify.
	Revoke(ctx context.Context, tokens []string) error
	// LocalSources lists where tools keep this provider's credentials on a
	// developer machine.
	LocalSources() LocalSources
}

Provider is one credential issuer: it knows the token formats it hands out, how to ask whether one is still live, and how to revoke it.

A provider never stores or logs a token value, and never contacts its API from Find.

type Registry added in v0.5.0

type Registry struct {
	// contains filtered or unexported fields
}

Registry is the set of providers a scan looks for. It dispatches by Kind and merges the providers' findings into one offset-ordered list.

func NewRegistry added in v0.5.0

func NewRegistry(providers ...Provider) *Registry

NewRegistry builds a registry from providers, in report order.

func (*Registry) Find added in v0.5.0

func (r *Registry) Find(content []byte) []Token

Find returns every credential of every provider in content, sorted by offset, with line numbers filled in.

func (*Registry) Info added in v0.5.0

func (r *Registry) Info(kind Kind) KindInfo

Info describes the kind; the zero KindInfo for an unknown one.

func (*Registry) Provider added in v0.5.0

func (r *Registry) Provider(kind Kind) Provider

Provider returns the provider that issues credentials of this kind, or nil.

func (*Registry) ProviderName added in v0.5.0

func (r *Registry) ProviderName(kind Kind) string

ProviderName returns the name of the provider of this kind, or "".

func (*Registry) Providers added in v0.5.0

func (r *Registry) Providers() []Provider

Providers returns the registered providers in order.

func (*Registry) Revocable added in v0.5.0

func (r *Registry) Revocable(kind Kind) bool

Revocable reports whether the kind's provider revokes it through its API.

func (*Registry) RevokePage added in v0.5.0

func (r *Registry) RevokePage(kind Kind) string

RevokePage is where the owner revokes a credential of this kind by hand.

func (*Registry) Verify added in v0.5.0

func (r *Registry) Verify(ctx context.Context, tok Token) Verification

Verify dispatches to the token's provider.

type Token

type Token struct {
	Kind  Kind
	Value string
	// Offset is the byte offset of the token in the scanned content.
	Offset int
	// Line is the 1-based line the token starts on.
	Line int
	// ChecksumVerified reports whether the token carries a checksum that
	// was verified offline. Classic GitHub tokens do; every other format is
	// matched on shape alone.
	ChecksumVerified bool
	// Attribution is what the token's own shape says about its owner, without
	// contacting the provider: a team id in a Slack token, for example. Empty
	// when the format carries nothing of the sort.
	Attribution string
}

Token is one credential found in scanned content.

func ScanPrefix added in v0.5.0

func ScanPrefix(found []Token, content []byte, prefix string, at func(start int) (Token, bool)) []Token

ScanPrefix finds every occurrence of prefix in content and calls at with its offset; at returns the token when the bytes there have the exact shape. Matches are appended to found.

func (Token) Fingerprint

func (t Token) Fingerprint() string

Fingerprint returns a short, stable, non-reversible identifier for the token value: the first 16 hex characters of its SHA-256. It is safe to put in logs and allow-lists.

type Verification

type Verification struct {
	Status VerifyStatus `json:"status"`
	// Detail describes what the credential gives access to: user and scopes,
	// the workspace of a Slack token, the number of repositories an
	// installation token reaches.
	Detail string `json:"detail,omitempty"`
	// ClientID is the id of the application the credential was issued to,
	// when the provider reports one.
	ClientID string `json:"client_id,omitempty"`
	// App is the name of that application when patty knows the client id.
	App string `json:"app,omitempty"`
	// Expires is when the credential stops working, for credentials that expire.
	Expires string `json:"expires,omitempty"`
}

Verification is the result of Provider.Verify.

func (Verification) Issuer added in v0.2.0

func (v Verification) Issuer() string

Issuer names the application a credential was issued to: the known app name, else the raw client id, else "".

type VerifyStatus

type VerifyStatus string

VerifyStatus is the outcome of checking a credential against its provider.

const (
	// StatusActive means the provider accepted the credential: it is live and must be revoked.
	StatusActive VerifyStatus = "active"
	// StatusRevoked means the provider explicitly rejected the credential as invalid.
	StatusRevoked VerifyStatus = "revoked"
	// StatusUnverifiable means the credential family cannot be checked without side effects.
	StatusUnverifiable VerifyStatus = "unverifiable"
	// StatusUnknown means the check could not be completed (network, rate
	// limit, an unexpected answer). It is never treated as proof of anything.
	StatusUnknown VerifyStatus = "unknown"
)

Directories

Path Synopsis
Package github is the GitHub credential provider: classic and fine-grained personal access tokens, OAuth and GitHub App tokens.
Package github is the GitHub credential provider: classic and fine-grained personal access tokens, OAuth and GitHub App tokens.
Package providers assembles the credential providers patty ships with.
Package providers assembles the credential providers patty ships with.
Package slack is the Slack credential provider: bot, user, app-level, refresh and configuration tokens, and incoming webhook URLs.
Package slack is the Slack credential provider: bot, user, app-level, refresh and configuration tokens, and incoming webhook URLs.

Jump to

Keyboard shortcuts

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