Documentation
¶
Index ¶
- Variables
- func ClearFindingFilters()
- func DedupeFindings(emit func([]Finding) error) func([]Finding) error
- func IsNameSecretIndicator(name string, rules []Rule) bool
- func IsSecretValue(name, value string, rules []Rule, path string) bool
- func IsSourceFile(path string) bool
- func ParseHumanDuration(s string) (time.Duration, error)
- func RegisterFindingFilter(f FindingFilter)
- func Scan(root string, resolver *ConfigResolver, opts ScanRunOptions, ...) error
- func ScanGitHistory(root string, resolver *ConfigResolver, opts GitHistoryOptions, ...) error
- func ShouldScan(path string, policy FilePolicy) bool
- func Walk(root string, fn func(string) error) error
- type Config
- type ConfigResolver
- type Correlation
- type CorrelationConfig
- type CustomDetector
- type Detector
- type DetectorConfig
- type DotenvDetector
- type ExaminationFocus
- type FilePolicy
- type Filter
- type FilterConfig
- type FilterConfigs
- type Finding
- type FindingFilter
- type FindingMatcher
- type GitHistoryOptions
- type GitProvenance
- type INIDetector
- type InfoRule
- type InfoRuleConfig
- type JSONDetector
- type JWT
- type Meta
- type NameRegexEntry
- type NamedRegex
- type PropertiesDetector
- type Rule
- type RuleConfig
- type RuleSet
- type ScanMode
- type ScanOptions
- type ScanRunOptions
- type SlnDetector
- type SourceDetector
- type ValuePattern
- type XMLDetector
- type YAMLDetector
Constants ¶
This section is empty.
Variables ¶
var RepoConfigNames = []string{".confessecrets.yaml", ".confessecrets.yml"}
RepoConfigNames are the file names looked for at a repository root (a directory containing a ".git" entry). The first one found provides a repo-local config that overrides the base config for files within that repository.
Functions ¶
func ClearFindingFilters ¶ added in v0.0.8
func ClearFindingFilters()
ClearFindingFilters removes every registered global finding filter.
func DedupeFindings ¶ added in v0.0.8
DedupeFindings wraps an emit callback so each distinct (file, secret value) pair — the value identified by its ValueSHA256 — is reported only the first time it is seen; later findings carrying the same value in the same file are dropped. The same value appearing in a *different* file is still reported: every file needing remediation surfaces, while repeats of a value within one file — or across the many historical versions of one file in a git history scan — collapse to the first occurrence. Because both Scan and ScanGitHistory emit in a stable order (walk order and oldest-commit-first respectively), "first seen" is deterministic; in a history scan the survivor is the oldest commit that introduced the value to that path.
Filtered findings (kept via IncludeFiltered) are tracked separately from unfiltered ones, so a value's filtered occurrence does not suppress a real finding of the same value. Values embedded under Correlated are not considered — a correlated partner never suppresses a later top-level finding. Batches left empty after deduplication are not emitted.
func IsNameSecretIndicator ¶ added in v0.0.8
IsNameSecretIndicator reports whether name signals a secret under any of rules: it matches at least one of a rule's name patterns and none of that rule's IgnoreNamePatterns. It is the name gate of the name-driven pipeline, exposed for callers embedding the scanner's heuristics.
func IsSecretValue ¶ added in v0.0.8
IsSecretValue reports whether value reads as a secret under any of rules when paired with name — the value side of the name-driven pipeline, without the name gate (pair it with IsNameSecretIndicator for the full pipeline). Per rule, the ignore lists and placeholder checks run first, then definite secret evidence (JWT, private key, URL credentials, connection string) or the likely-secret heuristics decide. path, when non-empty, supplies the per-file hints (language/format, dependency manifest) some heuristics read; pass "" when no file applies.
func IsSourceFile ¶ added in v0.0.3
IsSourceFile reports whether path is a source-code file handled by the tree-sitter SourceDetector (as opposed to a structured-config format). It lets callers include or exclude source scanning by file.
func ParseHumanDuration ¶ added in v0.0.8
ParseHumanDuration parses a duration written the way people say it — "2 years", "6 months", "90 days", "3w" — as well as anything Go's time.ParseDuration accepts ("72h", "30m"). Calendar units use fixed approximations: a day is 24h, a week 7 days, a month 30 days, a year 365 days. The duration must be positive.
func RegisterFindingFilter ¶ added in v0.0.8
func RegisterFindingFilter(f FindingFilter)
RegisterFindingFilter appends f to the global finding-filter chain. Every finding produced by any detector is offered to each registered filter in registration order; the first filter to return false drops it. Register all filters before scanning begins.
func Scan ¶ added in v0.0.8
func Scan(root string, resolver *ConfigResolver, opts ScanRunOptions, emit func(findings []Finding) error) error
Scan is the full scanning pipeline over a file or directory tree: it walks root, resolves the effective config for each path (honoring repo-local configs via resolver), applies the allow/deny file policy and the scan mode, scans each eligible file, and calls emit with every file's findings in walk order (files without findings are not emitted). An error from emit aborts the walk and is returned.
func ScanGitHistory ¶ added in v0.0.8
func ScanGitHistory(root string, resolver *ConfigResolver, opts GitHistoryOptions, emit func(findings []Finding) error) error
ScanGitHistory is the Scan counterpart for git history: instead of walking the working tree it visits every unique blob reachable from any ref (including deleted files and unmerged branches) and scans each one exactly once, no matter how many commits contain it. root must be inside a git repository; the repository root is discovered by climbing from root, and the whole history is scanned regardless of which subdirectory root names.
File paths on findings are repo-relative (the path the blob was first seen at), and each finding carries GitProvenance naming the oldest commit containing the blob. The effective config is resolved once at root — the current repo-local config governs the entire history — and the allow/deny policy and scan mode gate blobs by their repo-relative path just as a tree scan gates disk paths. An error from emit aborts the scan and is returned.
func ShouldScan ¶
func ShouldScan(path string, policy FilePolicy) bool
ShouldScan reports whether path passes the configured allow/deny policy.
Types ¶
type Config ¶
type Config struct {
Files FilePolicy `yaml:"files"`
Rules []RuleConfig `yaml:"rules"`
Detectors []DetectorConfig `yaml:"detectors"`
// Filter is an optional list of filter rules. Each rule is an expr-lang
// expression evaluated against every finding; what happens to a match depends
// on the rule's action (drop it, or tag it). See FilterConfig and Filter for
// the available variables. Empty means no filtering.
Filter FilterConfigs `yaml:"filter"`
// Correlations is an optional list of correlation rules. Each pairs a primary
// finding with one or more partner findings seen just before it in the same
// file; on a match the primary embeds the partners (which are dropped from the
// top-level results) and all are tagged. See CorrelationConfig.
Correlations []CorrelationConfig `yaml:"correlations"`
// Info is an optional list of informational-finding rules. Each is an expr-lang
// predicate over a value and its key name that, on a match, surfaces the value
// as a levelInfo finding ("info:<id>") — a recognized non-credential identifier
// such as a cloud account/tenant/subscription ID. They extend a built-in set
// (see builtinInfoRules) and are evaluated before it. See InfoRuleConfig.
Info []InfoRuleConfig `yaml:"info"`
// Stopwords are extra non-secret words applied across all rules. As with the
// built-in stopword set, a name-driven candidate
// is dropped when its value contains (case-insensitively) any of these as a
// substring. They extend, never replace, the always-on built-in set. Use this
// to silence project-specific placeholders such as "redacted".
Stopwords []string `yaml:"stopwords"`
// JoinedEnvPrefixes are env-variable family prefixes joined to their kind
// word with no separator — libpq's PGPASSWORD/PGHOST/PGUSER. Separator-
// delimited families (PG_DB_*, MYSQL_*) group automatically; joined ones are
// invisible to word splitting and must be named here for source-code
// env-context enrichment to pair them. Matched case-insensitively.
JoinedEnvPrefixes []string `yaml:"joined_env_prefixes"`
}
func LoadConfig ¶
LoadConfig reads and parses the scanner configuration from path.
type ConfigResolver ¶ added in v0.0.3
type ConfigResolver struct {
// contains filtered or unexported fields
}
ConfigResolver resolves the effective scanner config for a file path. When enabled, it honors repo-local config files (see RepoConfigNames) discovered at repository roots: a file is governed by the config of its nearest enclosing repository, falling back to the base config when that repo has none. A repository root acts as a boundary — a repo without its own config uses the base config rather than inheriting an outer repo's. Results are memoized per directory, so each repo root is stat'd and parsed at most once.
func NewConfigResolver ¶ added in v0.0.3
func NewConfigResolver(base Config, baseSet RuleSet, enabled bool, root string) *ConfigResolver
NewConfigResolver builds a resolver over base/baseSet. enabled toggles repo-local config discovery; root bounds the upward search so the resolver never climbs above the scanned tree.
func (*ConfigResolver) Resolve ¶ added in v0.0.3
func (r *ConfigResolver) Resolve(path string) (Config, RuleSet)
Resolve returns the config and compiled rule set that should govern scanning path.
func (*ConfigResolver) ResolveDir ¶ added in v0.0.8
func (r *ConfigResolver) ResolveDir(dir string) (Config, RuleSet)
ResolveDir returns the config and compiled rule set governing files directly in dir. It is Resolve for callers that have a directory rather than a file path, such as the git history scan resolving config once at the repo root.
type Correlation ¶ added in v0.0.5
Correlation is a compiled CorrelationConfig. Exactly one form is active: structured (match + partners) or expression (program != nil).
func CompileCorrelations ¶ added in v0.0.5
func CompileCorrelations(cfgs []CorrelationConfig) ([]Correlation, error)
CompileCorrelations turns parsed correlation configs into ready-to-use rules, compiling their matchers or expression. A rule with a non-empty `when` is the expression form; otherwise it is structured and must list at least one partner. The applied tag defaults to the rule id. The built-in correlations are appended after the user-configured ones, so a user rule takes precedence when both could claim the same primary (first match per primary wins).
type CorrelationConfig ¶ added in v0.0.5
type CorrelationConfig struct {
ID string `yaml:"id"`
Match FindingMatcher `yaml:"match"`
Partners []FindingMatcher `yaml:"partners"`
When string `yaml:"when"`
Tag string `yaml:"tag"`
}
CorrelationConfig defines a relationship between findings: a primary finding (matched by Match, or the When expression's `current`) is enriched when every partner is present among the recent prior findings of the same file. It accepts two forms — structured (Match + Partners) or an expr-lang expression (When, with `current` and the `prev` finding-list in scope). On a match the partners are embedded into the primary, dropped from the top-level results, and all are tagged with Tag (defaulting to ID).
type CustomDetector ¶ added in v0.0.3
type CustomDetector struct {
Name string
Keywords []string // lowercased
Regexes []NamedRegex
Primary *regexp.Regexp // one of Regexes' patterns; supplies the reported value
ExcludeRegexes []*regexp.Regexp
ExcludeWords []string // lowercased
MinEntropy float64
// SecretType is the validated Finding.Type for this detector's matches, or
// "" to derive it from the detector and key names.
SecretType string
}
CustomDetector is a compiled DetectorConfig, ready to match against values. Regexes is kept sorted by name so iteration and primary selection stay deterministic despite Go's randomized map ordering.
func CompileDetectors ¶ added in v0.0.3
func CompileDetectors(configs []DetectorConfig) ([]CustomDetector, error)
CompileDetectors turns parsed custom-detector configs into ready-to-use CustomDetectors, compiling their regular expressions, resolving the primary regex, and lowercasing keyword/exclude-word lists for case-insensitive matching. It mirrors CompileRules and fails on the first invalid pattern.
type Detector ¶
Detector parses one file format's bytes (already BOM-stripped) into findings. Each supported format provides a concrete implementation.
type DetectorConfig ¶ added in v0.0.3
type DetectorConfig struct {
// Name labels the detector and appears in findings as "custom:<name>".
Name string `yaml:"name"`
// Keywords gate the detector: at least one must be present (case-insensitive)
// in the value or its key name before the regexes are evaluated. An empty
// list means the detector always runs its regexes.
Keywords []string `yaml:"keywords"`
// Regex maps a name to a pattern; every pattern must match the value for the
// detector to fire. A pattern's first capture group, when present, is the
// reported secret, otherwise the whole match is.
Regex map[string]string `yaml:"regex"`
// PrimaryRegexName selects which regex supplies the reported/entropy-checked
// value; it defaults to the alphabetically first regex when omitted.
PrimaryRegexName string `yaml:"primary_regex_name"`
// ExcludeRegexesMatch drops a match whose primary value matches any of these.
ExcludeRegexesMatch []string `yaml:"exclude_regexes_match"`
// ExcludeWords drops a candidate when any of these appears (case-insensitive)
// in the value or its key name.
ExcludeWords []string `yaml:"exclude_words"`
// Entropy, when > 0, drops matches whose primary value has Shannon entropy
// (bits per symbol) below the threshold.
Entropy float64 `yaml:"entropy"`
// SecretType, when set, is the Finding.Type reported on this detector's
// matches. It must be one of the secretType* vocabulary (e.g. "api-key",
// "token"); compilation fails on an unknown value. When omitted, the type is
// derived from the detector's name and the key name as usual.
SecretType string `yaml:"secret_type"`
}
DetectorConfig is a trufflehog-style custom value-pattern detector as parsed from YAML, recognizing a secret by the shape of the value alone. The schema mirrors trufflehog's custom detectors (https://trufflesecurity.com/docs/custom-detectors): a detector fires when a keyword is present and every named regex matches. Live HTTP `verify` endpoints are intentionally unsupported — confessecrets is an offline scanner that redacts values rather than exfiltrating them — so that field is ignored.
type DotenvDetector ¶
type DotenvDetector struct{}
DotenvDetector handles dotenv-style files (.env and its variants). It parses with joho/godotenv and falls back to line-based scanning for input that doesn't parse cleanly, mirroring the JSON/YAML detectors.
type ExaminationFocus ¶ added in v0.0.5
type ExaminationFocus struct {
File string
Path string
Line int
Name string
Value string
PrevFindings []Finding
}
ExaminationFocus bundles the single item under inspection for value-pattern detection: where it lives (File/Path/Line), how it is labelled (Name), its scalar Value, and a snapshot of the most-recent prior findings for this file, kept for correlation context. Line is the 1-based source line, 0 when unknown.
type FilePolicy ¶
type Filter ¶ added in v0.0.3
Filter is a compiled filter rule: an expr-lang (https://expr-lang.org) predicate paired with the action to take on the findings it matches. A "filter"-action rule drops matches; a "tag"-action rule keeps them and adds its ID to their tags. It lets a config suppress (or label) whole classes of findings by their computed properties, e.g. `entropy <= 4 && name_value_similarity > 0.65` to drop low-entropy near-echoes.
The variables available to an expression are:
entropy (number) Shannon entropy of the value, bits/symbol name_value_similarity (number) name/value similarity, 0..1 value_length (number) length of the raw value in bytes name (string) the key name value (string) the raw (unredacted) value type (string) what kind of secret (e.g. "password", "api-key") reason (string) why the value was flagged lang (string) source language / config format (e.g. "json") level (string) severity: "high" (secret) or "info" line (number) 1-based source line, or 0 if not line-oriented file, path, name_path, value_path (string) location fields
expr-lang built-ins (matches, contains, startsWith, endsWith, lower, len, ...) are available, so richer rules like `value matches "(?i)example$"` work too.
type FilterConfig ¶ added in v0.0.5
type FilterConfig struct {
// ID labels the rule; it is the tag added to findings when Action is "tag".
ID string `yaml:"id"`
// Action is "filter" (drop matches, the default) or "tag" (keep and tag them).
Action string `yaml:"action"`
// Filter is the expr-lang expression evaluated against each finding.
Filter string `yaml:"filter"`
}
FilterConfig is one entry of the top-level filter list. It accepts two YAML forms: a bare scalar (the expression, with the default "filter" action) or a mapping with id/action/filter keys.
func (*FilterConfig) UnmarshalYAML ¶ added in v0.0.5
func (f *FilterConfig) UnmarshalYAML(value *yaml.Node) error
UnmarshalYAML accepts either a scalar expression (action defaults to "filter") or an {id, action, filter} mapping.
type FilterConfigs ¶ added in v0.0.5
type FilterConfigs []FilterConfig
FilterConfigs is the top-level filter list. It accepts a YAML sequence of entries or, for convenience, a single bare entry (scalar or mapping) treated as a one-element list.
func (*FilterConfigs) UnmarshalYAML ¶ added in v0.0.5
func (fs *FilterConfigs) UnmarshalYAML(value *yaml.Node) error
type Finding ¶
type Finding struct {
// File is the path to the source file. Top-level findings always set it; it is
// cleared (and so omitted) on findings embedded under Correlated, since a
// correlated partner is always in the same file as its primary — only its
// in-file location (Path) is meaningful there.
File string `json:"file,omitempty"`
// Path is the in-document location: a structured locator such as "$.db.password"
// for parsed config, or an INI "[section] line:N". It is empty (and omitted)
// when File and Line already carry the full location, as in the plain
// line-oriented formats.
Path string `json:"path,omitempty"`
// Line is the 1-based source line the finding sits on. It is 0 (and omitted)
// when the format supplies no position, e.g. a relaxed-JSON fallback parse or
// a structured path with no line index.
Line int `json:"line,omitempty"`
// Lang is the source language or config format of the file the finding came
// from (e.g. "python", "json"). Omitted for unsupported file types.
Lang string `json:"lang,omitempty"`
// Level is the severity of the finding: "high" for a detected secret (the
// default) or "info" for an informational match such as a recognized service
// URL that is worth surfacing but is not itself a credential.
Level string `json:"level,omitempty"`
NamePath string `json:"name_path"`
ValuePath string `json:"value_path"`
Name string `json:"name"`
Value string `json:"value"`
RawValue string `json:"raw_value"`
ValueSHA256 string `json:"value_sha256"`
Entropy float64 `json:"entropy"`
NameValueSimilarity float64 `json:"name_value_similarity"`
// Type names what kind of secret the finding is (e.g. "password", "api-key",
// "jwt" — see the secretType* constants), where Reason records why it was
// flagged. Omitted on informational (levelInfo) findings, which are not
// credentials.
Type string `json:"type,omitempty"`
Reason string `json:"reason"`
// Tags are free-form labels attached to the finding: the ID of any "tag"-action
// filter rule the finding matched, and any correlation tag. The source language
// or config format is carried in the dedicated Lang field rather than a tag.
// Omitted when empty.
Tags []string `json:"tags,omitempty"`
// Filtered is set when the finding matched the config filter but was retained
// (via -show-filtered) instead of dropped; FilteredReason holds the expression
// that excluded it. Both are omitted from normal, unfiltered findings.
Filtered bool `json:"filtered,omitempty"`
FilteredReason string `json:"filtered_reason,omitempty"`
Meta *Meta `json:"meta,omitempty"`
// Git carries commit provenance when the finding came from a git history
// scan rather than the working tree; nil (and omitted) otherwise.
Git *GitProvenance `json:"git,omitempty"`
// correlation rule (e.g. the client_id paired with this client_secret).
// Embedded secondaries are removed from the top-level results and surface only
// nested here.
Correlated []Finding `json:"correlated,omitempty"`
}
type FindingFilter ¶ added in v0.0.8
FindingFilter is a user-defined predicate over a freshly built finding. Returning false drops the finding before it enters any results; returning true keeps it. Filters see the finding as constructed (RawValue included), before correlation, Lang stamping, or the config filter rules run.
type FindingMatcher ¶ added in v0.0.5
type FindingMatcher struct {
NameRegex string `yaml:"name_regex"`
ReasonRegex string `yaml:"reason_regex"`
PathRegex string `yaml:"path_regex"`
Expr string `yaml:"expr"`
}
FindingMatcher matches a single finding. It has two mutually exclusive forms: the regex form matches by one or more finding fields (all set fields must match, AND); the expression form (Expr) is an expr-lang predicate evaluated against the finding's fields (the same variables a filter expression sees, e.g. `name`, `reason`, `entropy`). An empty matcher matches nothing.
type GitHistoryOptions ¶ added in v0.0.8
type GitHistoryOptions struct {
ScanRunOptions
// MaxDepth, when positive, limits the scan to the N most recent commits
// across all refs, ordered by committer time.
MaxDepth int
// MaxAge, when positive, skips commits whose committer time is more than
// MaxAge before now (see ParseHumanDuration for accepting values like
// "2 years"). Content introduced before the cutoff but still present in an
// in-window commit is still scanned, attributed to the oldest in-window
// commit containing it.
MaxAge time.Duration
}
GitHistoryOptions tunes a git history scan. The embedded ScanRunOptions carry the same knobs a tree scan takes; the zero value scans all history.
type GitProvenance ¶ added in v0.0.8
type GitProvenance struct {
Commit string `json:"commit"`
Blob string `json:"blob"`
Author string `json:"author,omitempty"`
AuthorDate string `json:"author_date,omitempty"`
}
GitProvenance records where in git history a finding's content entered the repository: the oldest commit (by committer time) whose tree contains the blob the finding was detected in.
type INIDetector ¶
type INIDetector struct{}
INIDetector handles INI-style files (sections plus key=value pairs). It parses structurally with go-ini and falls back to line-based scanning for files that don't parse cleanly, mirroring the JSON/YAML detectors.
type InfoRule ¶ added in v0.0.5
type InfoRule struct {
ID string
// contains filtered or unexported fields
}
InfoRule is a compiled informational-finding rule: an expr-lang (https://expr-lang.org) predicate over a value and its key name that, when it matches, yields a levelInfo finding reasoned "info:<id>". Info rules recognize non-credential identifiers worth surfacing for inventory — cloud account, tenant, and subscription IDs — without raising them to the severity of a secret. They are data-driven so new identifiers can be added via config rather than code (see builtinInfoRules for the shipped set and Config.Info to extend).
The variables and helpers available to an expression are:
name (string) the key name (e.g. "subscription_id")
value (string) the raw scalar value
words (func) -> []string the key split into lowercase identifier words, so
camelCase/snake_case/kebab-case all compare equally:
words("subscriptionId") == ["subscription", "id"].
expr-lang built-ins (matches, contains, in, lower, startsWith, ...) are available, so a rule reads e.g.
"subscription" in words(name) && value matches "(?i)^[0-9a-f-]{36}$"
type InfoRuleConfig ¶ added in v0.0.5
type InfoRuleConfig struct {
// ID labels the rule and appears in findings as "info:<id>".
ID string `yaml:"id"`
// Match is the expr-lang predicate; a true result yields the info finding.
Match string `yaml:"match"`
}
InfoRuleConfig is one informational-finding rule as parsed from YAML. A rule fires when its expr-lang Match predicate (evaluated over the value and its key name) is true, surfacing the value as a levelInfo finding reasoned "info:<id>". It accepts two YAML forms: a mapping with id/match keys, or a bare scalar treated as the match expression (the id then defaults to the expression itself). See InfoRule for the variables and helpers a Match can reference.
func (*InfoRuleConfig) UnmarshalYAML ¶ added in v0.0.5
func (c *InfoRuleConfig) UnmarshalYAML(value *yaml.Node) error
UnmarshalYAML accepts either a scalar match expression (id defaults to the expression) or an {id, match} mapping.
type JSONDetector ¶
type JSONDetector struct{}
JSONDetector handles .json/.jsonc files. It parses structurally when possible and falls back to line-based scanning for non-standard JSON.
type JWT ¶ added in v0.0.5
type JWT struct {
Issuer string `json:"issuer,omitempty"`
Iat int64 `json:"iat,omitempty"`
Expiration int64 `json:"expiration,omitempty"`
IsExpired bool `json:"is_expired,omitempty"`
Header map[string]interface{} `json:"header,omitempty"`
Extra map[string]interface{} `json:"extra,omitempty"`
}
JWT holds claims and the header decoded from a JSON Web Token value. The standard iss/iat/exp claims map to dedicated fields; the decoded header (alg/typ/kid, ...) lives in Header and every other claim in Extra. All fields are optional and omitted from output when absent.
type Meta ¶
type Meta struct {
JWT *JWT `json:"jwt,omitempty"`
Username string `json:"username,omitempty"`
AppId string `json:"app_id,omitempty"`
Host string `json:"host,omitempty"`
URL string `json:"url,omitempty"`
ClientID string `json:"client_id,omitempty"`
ClientKey string `json:"client_key,omitempty"`
Extra map[string]interface{} `json:"extra,omitempty"`
}
Meta holds optional, value-derived metadata attached to a finding. JWT is populated from JSON Web Token values; the identity fields (Username, Host, URL, ClientID, ClientKey) are derived from URL credentials, connection-string values, and correlated partner findings. All fields are optional and omitted from output when absent.
type NameRegexEntry ¶ added in v0.0.3
NameRegexEntry is one entry of a rule's name_regexes list. It accepts two YAML forms: a bare scalar (the regex, unnamed) or a mapping with `name` and `regex` keys. The name is an optional human-readable label for the pattern.
func (*NameRegexEntry) UnmarshalYAML ¶ added in v0.0.3
func (e *NameRegexEntry) UnmarshalYAML(value *yaml.Node) error
UnmarshalYAML accepts either a scalar regex string or a {name, regex} mapping.
type NamedRegex ¶ added in v0.0.3
NamedRegex is a compiled name pattern with its optional label.
type PropertiesDetector ¶
type PropertiesDetector struct{}
PropertiesDetector handles Java-style .properties files. It parses with magiconair/properties and falls back to line-based scanning for input that doesn't parse cleanly, mirroring the JSON/YAML detectors.
type Rule ¶
type Rule struct {
NamePaths []string
ValuePaths []string
NameRegexes []NamedRegex
MinValueLen int
MinEntropy float64
HighEntropyThreshold float64
MaxNameValueSimilarity float64
IgnoreNamePatterns []*regexp.Regexp
IgnoreValuePrefixes []string
IgnoreValuePatterns []*regexp.Regexp
// Stopwords are the effective extra non-secret words (lowercased) checked by
// substring containment on top of the built-in stopword set. They come from
// the global Config.Stopwords and are copied onto every rule at compile time
// (see CompileConfig). Nil when none are configured.
Stopwords []string
}
func CompileRules ¶
func CompileRules(configs []RuleConfig) ([]Rule, error)
CompileRules turns parsed rule configs into ready-to-use Rules, compiling their regular expressions and applying defaults.
type RuleConfig ¶
type RuleConfig struct {
NamePaths []string `yaml:"name_paths"`
ValuePaths []string `yaml:"value_paths"`
// NameRegexes is a list of name patterns. Each entry is either a bare regex
// string or a {name, regex} mapping; a name matching any entry signals a
// secret.
NameRegexes []NameRegexEntry `yaml:"name_regexes"`
MinValueLen int `yaml:"min_value_len"`
// MinEntropy, when > 0, gates name-driven findings: a value flagged because
// its key name looks secret-y must have at least this Shannon entropy
// (bits/symbol) or it is treated as a placeholder and dropped. Values that
// carry a definite secret reason (JWT, private key, URL credentials) bypass
// the gate.
MinEntropy float64 `yaml:"min_entropy"`
// HighEntropyThreshold, when > 0, enables a generic detector that flags any
// value whose Shannon entropy meets the threshold, regardless of key name.
HighEntropyThreshold float64 `yaml:"high_entropy_threshold"`
// MaxNameValueSimilarity, when > 0, drops name-driven findings whose value is
// at least this similar (0..1) to the key name — near-echoes such as
// password="password1" or passwd="passw0rd" that the exact-echo check misses.
// Similarity is the max of normalized Levenshtein and Jaro-Winkler.
MaxNameValueSimilarity float64 `yaml:"max_name_value_similarity"`
IgnoreNamePatterns []string `yaml:"ignore_name_patterns"`
IgnoreValuePrefixes []string `yaml:"ignore_value_prefixes"`
IgnoreValuePatterns []string `yaml:"ignore_value_patterns"`
}
type RuleSet ¶ added in v0.0.3
type RuleSet struct {
Rules []Rule
Detectors []CustomDetector
Filters []*Filter
Correlations []Correlation
// InfoRules recognize non-credential identifiers (cloud account/tenant/
// subscription IDs) and surface them as levelInfo findings. See InfoRule.
InfoRules []InfoRule
// JoinedEnvPrefixes are the normalized (lowercased) no-separator env family
// prefixes from Config.JoinedEnvPrefixes, read by the source detector's
// env-context enrichment.
JoinedEnvPrefixes []string
}
RuleSet is the compiled detection configuration applied to a file: the name-driven Rules, the value-shape Detectors (custom, trufflehog-style), the post-detection Filters, and the cross-finding Correlations. They travel together so every file is scanned under one effective config, including repo-local overrides.
func CompileConfig ¶ added in v0.0.3
CompileConfig compiles a parsed Config into the RuleSet used to scan a file, pairing its name-driven rules with its value-shape custom detectors. It is the single entry point for turning loaded config (base or repo-local) into a ready-to-use RuleSet.
type ScanMode ¶ added in v0.0.8
type ScanMode string
ScanMode selects which file classes a scan visits: everything, only source code, or only structured config.
type ScanOptions ¶ added in v0.0.3
type ScanOptions struct {
// IncludeFiltered keeps findings excluded by the config filter in the results,
// marking each Filtered with its FilteredReason, instead of dropping them.
IncludeFiltered bool
}
ScanOptions tunes how ScanFile post-processes findings.
type ScanRunOptions ¶ added in v0.0.8
type ScanRunOptions struct {
// Mode selects which file classes are visited; the zero value behaves as
// ScanAll.
Mode ScanMode
// IncludeFiltered keeps findings excluded by the config filter in the
// results, marking each Filtered with its FilteredReason, instead of
// dropping them.
IncludeFiltered bool
// OnSkip, when non-nil, is called for each file that could not be scanned
// (e.g. its bytes could not be read). Skipped files do not stop the walk.
OnSkip func(path string, err error)
}
ScanRunOptions tunes a tree-level Scan.
type SlnDetector ¶ added in v0.0.8
type SlnDetector struct{}
SlnDetector handles Visual Studio solution (.sln) files. The format is line-oriented: top-level "key = value" headers (e.g. VisualStudioVersion), Project declarations, and GlobalSection/ProjectSection blocks of key/value pairs. There is no maintained Go parser for the format, so this walks it directly, mirroring the INI detector's line scan. The successor .slnx and .slnf formats are XML and JSON respectively and route to those detectors.
type SourceDetector ¶ added in v0.0.3
type SourceDetector struct{}
SourceDetector scans general-purpose source code (Python, JavaScript, TypeScript, Go, Java, C#, Ruby, PHP, Kotlin, Rust) for hardcoded secrets using tree-sitter. Unlike the structured-config detectors, it distinguishes a secret *literal* from a runtime lookup: it flags `password = "hunter2"` (the value node is a string literal) but not `password = os.environ.get("SECRET")` (the value node is a call), which regex-only scanners get wrong.
Parsing uses a pure-Go tree-sitter runtime with the grammars embedded in the binary (github.com/odvcencio/gotreesitter), so there is nothing to install, download, or compile at runtime, and the build stays CGO-free and cross-compilable.
type ValuePattern ¶
type ValuePattern struct {
ID string
Regex *regexp.Regexp
// Allow are per-rule allowlist regexes (carried from the source ruleset): when the
// Regex matches but any Allow regex also matches the value, it is suppressed
// (e.g. AWS example keys ending in EXAMPLE). Nil for the hand-curated rules.
Allow []*regexp.Regexp
}
ValuePattern is a value-shape rule that recognizes a secret by the shape of the value itself, independent of any surrounding key name.
type XMLDetector ¶
type XMLDetector struct{}
XMLDetector handles .xml files via streaming token scanning.
type YAMLDetector ¶
type YAMLDetector struct{}
YAMLDetector handles .yaml/.yml files, falling back to line-based scanning for templated YAML that doesn't parse cleanly.
Source Files
¶
- classify.go
- correlate.go
- dedupe.go
- detect.go
- detector_dotenv.go
- detector_ini.go
- detector_json.go
- detector_properties.go
- detector_sln.go
- detector_source.go
- detector_xml.go
- detector_yaml.go
- detectors.go
- duration.go
- files.go
- filter.go
- finding_filter.go
- githistory.go
- info.go
- meta.go
- models.go
- patterns.go
- patterns_builtin_gen.go
- patterns_gen.go
- patterns_url_gen.go
- repoconfig.go
- scan.go
- stopwords.go
- strutil.go