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
- func All(b []byte, ok func(byte) bool) bool
- func AlnumAt(content []byte, i int) bool
- func Do(client *http.Client, req *http.Request) (*http.Response, error)
- func Fingerprint(value string) string
- func IsAlnum(c byte) bool
- func IsDigit(c byte) bool
- func IsHex(c byte) bool
- func ReadBody(r io.Reader, limit int64) []byte
- func Redact(value string) string
- func Span(content []byte, start, limit int, ok func(byte) bool) int
- type DryRunRevoker
- type Kind
- type KindInfo
- type LocalSources
- type Provider
- type Registry
- func (r *Registry) Find(content []byte) []Token
- func (r *Registry) Info(kind Kind) KindInfo
- func (r *Registry) Provider(kind Kind) Provider
- func (r *Registry) ProviderName(kind Kind) string
- func (r *Registry) Providers() []Provider
- func (r *Registry) Revocable(kind Kind) bool
- func (r *Registry) RevokePage(kind Kind) string
- func (r *Registry) Verify(ctx context.Context, tok Token) Verification
- type Token
- type Verification
- type VerifyStatus
Constants ¶
const UserAgent = "patty"
UserAgent identifies patty to the provider APIs.
Variables ¶
This section is empty.
Functions ¶
func AlnumAt ¶ added in v0.5.0
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 Fingerprint ¶
Fingerprint returns the fingerprint of a raw token value.
Types ¶
type DryRunRevoker ¶ added in v0.5.0
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
// AuditNote says how to find out whether a leaked credential of this kind
// was used while it was exposed, and what the provider does on its own
// when it spots the leak. Shown for every finding, revoked or not.
AuditNote 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 credentials. A nil error
// means every request was accepted; the caller confirms the outcome with
// Verify.
Revoke(ctx context.Context, tokens []Token) 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
NewRegistry builds a registry from providers, in report order.
func (*Registry) Find ¶ added in v0.5.0
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
Info describes the kind; the zero KindInfo for an unknown one.
func (*Registry) Provider ¶ added in v0.5.0
Provider returns the provider that issues credentials of this kind, or nil.
func (*Registry) ProviderName ¶ added in v0.5.0
ProviderName returns the name of the provider of this kind, or "".
func (*Registry) Revocable ¶ added in v0.5.0
Revocable reports whether the kind's provider revokes it through its API.
func (*Registry) RevokePage ¶ added in v0.5.0
RevokePage is where the owner revokes a credential of this kind by hand.
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
// Secret is the material a credential needs besides Value when it is made
// of several strings: the secret access key found next to an AWS key id,
// and the session token of a temporary one. Its layout is the provider's
// business. Value alone identifies the credential; Secret is never
// printed, logged or fingerprinted.
Secret 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 ¶
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 aws is the AWS credential provider: the access keys of IAM users and the temporary access keys STS hands out.
|
Package aws is the AWS credential provider: the access keys of IAM users and the temporary access keys STS hands out. |
|
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. |