API Reference
The public API is intentionally small and typed.
pybetterleaks
Python-native bindings for Betterleaks.
GitScope
module-attribute
GitScope = Literal['worktree']
SUPPORTED_GIT_SCOPES
module-attribute
SUPPORTED_GIT_SCOPES: tuple[GitScope, ...] = ('worktree',)
BetterleaksConfig
dataclass
BetterleaksConfig(
rules: list[Rule] = list(),
title: Optional[str] = None,
description: Optional[str] = None,
extend: Optional[Extend] = None,
prefilter: Optional[ExprInput] = None,
filter: Optional[ExprInput] = None,
min_version: Optional[str] = None,
betterleaks_min_version: Optional[str] = None,
extend_base_path: Optional[PathInput] = None,
)
Typed Python representation of a Betterleaks TOML config.
to_toml
to_toml(
*, extend_base_path: Optional[PathInput] = None
) -> str
Serialize this config to Betterleaks-compatible TOML.
with_defaults
classmethod
with_defaults(
*,
rules: Optional[list[Rule]] = None,
disabled_rules: Optional[list[str]] = None,
title: Optional[str] = None,
description: Optional[str] = None,
prefilter: Optional[ExprInput] = None,
filter: Optional[ExprInput] = None,
min_version: Optional[str] = None,
betterleaks_min_version: Optional[str] = None,
) -> "BetterleaksConfig"
Create a config that extends Betterleaks' bundled defaults.
write
write(path: PathInput) -> Path
Write this config to path and return the resolved Path.
Expr
dataclass
Expr(value: str)
Betterleaks Expr expression used in filters and validation.
value
instance-attribute
value: str
Raw Expr source.
all_of
classmethod
all_of(*expressions: ExprInput) -> 'Expr'
Combine expressions with &&.
any_of
classmethod
any_of(*expressions: ExprInput) -> 'Expr'
Combine expressions with ||.
attribute
staticmethod
attribute(name: str = 'path', *, default: str = '') -> str
Return a Betterleaks Expr attribute lookup with a default value.
attribute_contains_any
classmethod
attribute_contains_any(
name: str, values: Sequence[str], *, default: str = ""
) -> "Expr"
Build filter.containsAny(get(attributes, name, default), values).
attribute_matches_any
classmethod
attribute_matches_any(
name: str, patterns: Sequence[str], *, default: str = ""
) -> "Expr"
Build filter.matchesAny(get(attributes, name, default), regex_patterns).
finding
staticmethod
finding(field: str = 'secret') -> str
Return a Betterleaks Expr reference such as finding["secret"].
finding_contains_any
classmethod
finding_contains_any(
values: Sequence[str], *, field: str = "secret"
) -> "Expr"
Build filter.containsAny(finding[field], values).
finding_matches_any
classmethod
finding_matches_any(
patterns: Sequence[str], *, field: str = "secret"
) -> "Expr"
Build filter.matchesAny(finding[field], regex_patterns).
git_commit_in
classmethod
git_commit_in(commits: Sequence[str]) -> 'Expr'
Build the modern equivalent of a commit allowlist predicate.
min_entropy
classmethod
min_entropy(
threshold: float, *, field: str = "secret"
) -> "Expr"
Build a rule filter that keeps only findings above an entropy threshold.
Betterleaks filter expressions return True when a finding should be
skipped, so this helper emits a "skip when entropy is too low" predicate.
not_
classmethod
not_(expression: ExprInput) -> 'Expr'
Negate an expression.
path_matches_any
classmethod
path_matches_any(patterns: Sequence[str]) -> 'Expr'
Build the modern equivalent of a path allowlist predicate.
token_efficiency
classmethod
token_efficiency(*, field: str = 'secret') -> 'Expr'
Build a filter predicate that skips token-efficient natural text.
Validation
Helpers for Betterleaks rule validate expressions.
bearer_get
staticmethod
bearer_get(
url: str,
success_check: str,
*,
token_field: str = "secret",
valid_status: int = 200,
invalid_statuses: Sequence[int] = (401, 403),
invalid_reason: str = "Unauthorized",
accept_json: bool = True,
) -> Expr
Build a common HTTP bearer-token validation expression.
invalid
classmethod
invalid(
*, reason: Optional[str] = None, **metadata: str
) -> Expr
Build {"result": "invalid"} with an optional reason.
needs_validation
classmethod
needs_validation(**metadata: str) -> Expr
Build {"result": "needs_validation"} with optional metadata.
result
staticmethod
result(status: str, **metadata: str) -> Expr
Build a structured validation result object expression.
unknown
classmethod
unknown(
response_expr: Optional[str] = None, **metadata: str
) -> Expr
Build an unknown validation result or validate.unknown(response) call.
valid
classmethod
valid(**metadata: str) -> Expr
Build {"result": "valid"} with optional metadata.
Extend
dataclass
Extend(
path: Optional[PathInput] = None,
url: Optional[str] = None,
use_default: bool = False,
disabled_rules: list[str] = list(),
)
Betterleaks [extend] configuration.
Rule
dataclass
Rule(
id: str,
description: str,
regex: Optional[str] = None,
keywords: list[str] = list(),
path: Optional[str] = None,
secret_group: Optional[int] = None,
entropy: Optional[float] = None,
tags: list[str] = list(),
specificity: Optional[int] = None,
filter: Optional[ExprInput] = None,
validate: Optional[ExprInput] = None,
required: list[RequiredRule] = list(),
skip_report: bool = False,
token_efficiency: bool = False,
)
Betterleaks [[rules]] detection rule.
path_rule
classmethod
path_rule(
*,
id: str,
description: str,
path: str,
tags: Optional[list[str]] = None,
filter: Optional[ExprInput] = None,
) -> "Rule"
Create a path-only rule for file/path based findings.
pem_private_key_rule
classmethod
pem_private_key_rule(
*,
id: str = "pem-private-key",
description: str = "PEM private key",
path: Optional[str] = None,
tags: Optional[list[str]] = None,
filter: Optional[ExprInput] = None,
) -> "Rule"
Create a rule for PEM private key blocks.
prefixed_token_rule
classmethod
prefixed_token_rule(
*,
id: str,
description: str,
prefix: str,
token_pattern: str = "[A-Za-z0-9_\\-]{16,}",
keywords: Optional[list[str]] = None,
secret_group: Optional[int] = None,
tags: Optional[list[str]] = None,
filter: Optional[ExprInput] = None,
validate: Optional[ExprInput] = None,
entropy: Optional[float] = None,
) -> "Rule"
Create a regex rule for a token with a literal prefix.
regex_rule
classmethod
regex_rule(
*,
id: str,
description: str,
regex: str,
keywords: Optional[list[str]] = None,
secret_group: Optional[int] = None,
tags: Optional[list[str]] = None,
filter: Optional[ExprInput] = None,
validate: Optional[ExprInput] = None,
entropy: Optional[float] = None,
) -> "Rule"
Create a common regex-based rule with ergonomic defaults.
RequiredRule
dataclass
RequiredRule(
id: str,
within_lines: Optional[int] = None,
within_columns: Optional[int] = None,
)
Composite rule dependency in [[rules.required]].
ScanResult
dataclass
ScanResult(
findings: list[Finding],
errors: list[ScanError],
betterleaks_version: str,
)
Result returned by scan_text and scan_dir.
betterleaks_version
instance-attribute
betterleaks_version: str
Betterleaks version bundled into the native bridge.
errors
instance-attribute
errors: list[ScanError]
Structured native errors. Empty means the scan succeeded.
findings
instance-attribute
findings: list[Finding]
Findings produced by the scan.
ok
property
ok: bool
Whether the scan completed without structured native errors.
Finding
dataclass
Finding(
rule_id: str,
description: Optional[str] = None,
file: Optional[str] = None,
line: Optional[int] = None,
column: Optional[int] = None,
end_line: Optional[int] = None,
end_column: Optional[int] = None,
secret: Optional[str] = None,
match: Optional[str] = None,
validation_status: Optional[str] = None,
validation_meta: dict[str, Any] = dict(),
tags: list[str] = list(),
attributes: dict[str, str] = dict(),
raw: dict[str, Any] = dict(),
)
Secret finding returned by Betterleaks.
attributes
class-attribute
instance-attribute
attributes: dict[str, str] = field(default_factory=dict)
Additional normalized attributes such as fingerprint and entropy.
column
class-attribute
instance-attribute
column: Optional[int] = None
One-based start column, if available.
description
class-attribute
instance-attribute
description: Optional[str] = None
Rule description, when provided by Betterleaks.
end_column
class-attribute
instance-attribute
end_column: Optional[int] = None
One-based end column, if available.
end_line
class-attribute
instance-attribute
end_line: Optional[int] = None
One-based end line, if available.
file
class-attribute
instance-attribute
file: Optional[str] = None
File path for directory scans, if available.
line
class-attribute
instance-attribute
line: Optional[int] = None
One-based start line, if available.
match
class-attribute
instance-attribute
match: Optional[str] = None
Matched text around the secret, when Betterleaks provides it.
raw
class-attribute
instance-attribute
raw: dict[str, Any] = field(default_factory=dict)
Forward-compatible raw Betterleaks fields.
rule_id
instance-attribute
rule_id: str
Betterleaks rule identifier.
secret
class-attribute
instance-attribute
secret: Optional[str] = None
Secret value, usually REDACTED unless redaction is disabled.
tags
class-attribute
instance-attribute
tags: list[str] = field(default_factory=list)
Rule tags.
validation_meta
class-attribute
instance-attribute
validation_meta: dict[str, Any] = field(
default_factory=dict
)
Additional validation metadata.
validation_status
class-attribute
instance-attribute
validation_status: Optional[str] = None
Validation status reported by Betterleaks.
ScanError
dataclass
ScanError(
code: str, message: str, detail: Optional[str] = None
)
Structured error returned by the native bridge.
code
instance-attribute
code: str
Stable machine-readable error code.
detail
class-attribute
instance-attribute
detail: Optional[str] = None
Optional native error detail.
message
instance-attribute
message: str
Human-readable error summary.
PyBetterleaksError
Bases: Exception
Base exception for PyBetterleaks errors.
ScanFailedError
ScanFailedError(
errors: Sequence[ScanError],
*,
result: Optional[ScanResult] = None,
)
ScanConfigError
ScanConfigError(
errors: Sequence[ScanError],
*,
result: Optional[ScanResult] = None,
)
ScanTargetError
ScanTargetError(
errors: Sequence[ScanError],
*,
result: Optional[ScanResult] = None,
)
ScanTimeoutError
ScanTimeoutError(
errors: Sequence[ScanError],
*,
result: Optional[ScanResult] = None,
)
UnsupportedScanError
UnsupportedScanError(
errors: Sequence[ScanError],
*,
result: Optional[ScanResult] = None,
)
InvalidScanRequestError
InvalidScanRequestError(
errors: Sequence[ScanError],
*,
result: Optional[ScanResult] = None,
)
NativeScanError
NativeScanError(
errors: Sequence[ScanError],
*,
result: Optional[ScanResult] = None,
)
ConfigFormatError
Bases: PyBetterleaksError, ValueError
Raised when a typed Betterleaks config cannot be serialized safely.
NativeLibraryError
Bases: PyBetterleaksError
Raised when the native Betterleaks bridge cannot be used.
NativeLibraryNotFoundError
NativeLibraryNotFoundError(
*, path: Path, system: str, machine: str
)
NativeCallError
Bases: NativeLibraryError
Raised when a native call fails before a structured scan response exists.
scan_text
scan_text(
text: str,
*,
config: Optional[BetterleaksConfig] = None,
config_path: Optional[PathInput] = None,
validation: bool = False,
validation_env_vars: Optional[Sequence[str]] = None,
redact: bool = True,
timeout_seconds: Optional[float] = None,
raise_on_error: bool = False,
_request_id: Optional[str] = None,
) -> ScanResult
Scan an in-memory text fragment for secrets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str
|
Text content to scan. |
required |
config
|
Optional[BetterleaksConfig]
|
Optional typed Betterleaks config. Mutually exclusive with |
None
|
config_path
|
Optional[PathInput]
|
Optional path to a Betterleaks configuration file. |
None
|
validation
|
bool
|
Enable Betterleaks validation when supported by the rule. |
False
|
validation_env_vars
|
Optional[Sequence[str]]
|
Environment variable names validation Expr may read. |
None
|
redact
|
bool
|
Replace secret values in findings with |
True
|
timeout_seconds
|
Optional[float]
|
Optional positive scan deadline in seconds. |
None
|
raise_on_error
|
bool
|
Raise a typed |
False
|
Returns:
| Type | Description |
|---|---|
ScanResult
|
A typed scan result containing findings, structured native errors, and |
ScanResult
|
the bundled Betterleaks version. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
NativeLibraryError
|
If the native library cannot load or returns malformed data. |
ScanFailedError
|
If |
scan_dir
scan_dir(
path: PathInput,
*,
config: Optional[BetterleaksConfig] = None,
config_path: Optional[PathInput] = None,
validation: bool = False,
validation_env_vars: Optional[Sequence[str]] = None,
redact: bool = True,
timeout_seconds: Optional[float] = None,
raise_on_error: bool = False,
_request_id: Optional[str] = None,
) -> ScanResult
Scan a directory with the bundled Betterleaks engine.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
PathInput
|
Directory path to scan. |
required |
config
|
Optional[BetterleaksConfig]
|
Optional typed Betterleaks config. Mutually exclusive with |
None
|
config_path
|
Optional[PathInput]
|
Optional path to a Betterleaks configuration file. |
None
|
validation
|
bool
|
Enable Betterleaks validation when supported by the rule. |
False
|
validation_env_vars
|
Optional[Sequence[str]]
|
Environment variable names validation Expr may read. |
None
|
redact
|
bool
|
Replace secret values in findings with |
True
|
timeout_seconds
|
Optional[float]
|
Optional positive scan deadline in seconds. |
None
|
raise_on_error
|
bool
|
Raise a typed |
False
|
Returns:
| Type | Description |
|---|---|
ScanResult
|
A typed scan result. Expected scan failures, such as an invalid config |
ScanResult
|
path or non-directory target, are represented as |
ScanResult
|
rather than raised exceptions. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
NativeLibraryError
|
If the native library cannot load or returns malformed data. |
ScanFailedError
|
If |
scan_git
scan_git(
path: PathInput,
*,
scope: GitScope = "worktree",
config: Optional[BetterleaksConfig] = None,
config_path: Optional[PathInput] = None,
validation: bool = False,
validation_env_vars: Optional[Sequence[str]] = None,
redact: bool = True,
timeout_seconds: Optional[float] = None,
raise_on_error: bool = False,
_request_id: Optional[str] = None,
) -> ScanResult
Scan a local Git worktree without invoking the Git executable.
Example
from pybetterleaks import scan_git
result = scan_git(".", scope="worktree", config_path=".betterleaks.toml")
for finding in result.findings:
print(f"{finding.file}:{finding.line} {finding.rule_id}")
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
PathInput
|
Repository root or a directory inside a Git worktree. |
required |
scope
|
GitScope
|
Git scan scope. Currently supports only |
'worktree'
|
config
|
Optional[BetterleaksConfig]
|
Optional typed Betterleaks config. Mutually exclusive with |
None
|
config_path
|
Optional[PathInput]
|
Optional path to a Betterleaks configuration file. |
None
|
validation
|
bool
|
Enable Betterleaks validation when supported by the rule. |
False
|
validation_env_vars
|
Optional[Sequence[str]]
|
Environment variable names validation Expr may read. |
None
|
redact
|
bool
|
Replace secret values in findings with |
True
|
timeout_seconds
|
Optional[float]
|
Optional positive scan deadline in seconds. |
None
|
raise_on_error
|
bool
|
Raise a typed |
False
|
Returns:
| Type | Description |
|---|---|
ScanResult
|
A typed scan result. Invalid repositories are represented as structured |
ScanResult
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
NativeLibraryError
|
If the native library cannot load or returns malformed data. |
ScanFailedError
|
If |
scan_text_async
async
scan_text_async(
text: str,
*,
config: Optional[BetterleaksConfig] = None,
config_path: Optional[PathInput] = None,
validation: bool = False,
validation_env_vars: Optional[Sequence[str]] = None,
redact: bool = True,
timeout_seconds: Optional[float] = None,
raise_on_error: bool = False,
) -> ScanResult
Async wrapper for scan_text with cooperative native cancellation.
scan_dir_async
async
scan_dir_async(
path: PathInput,
*,
config: Optional[BetterleaksConfig] = None,
config_path: Optional[PathInput] = None,
validation: bool = False,
validation_env_vars: Optional[Sequence[str]] = None,
redact: bool = True,
timeout_seconds: Optional[float] = None,
raise_on_error: bool = False,
) -> ScanResult
Async wrapper for scan_dir with cooperative native cancellation.
scan_git_async
async
scan_git_async(
path: PathInput,
*,
scope: GitScope = "worktree",
config: Optional[BetterleaksConfig] = None,
config_path: Optional[PathInput] = None,
validation: bool = False,
validation_env_vars: Optional[Sequence[str]] = None,
redact: bool = True,
timeout_seconds: Optional[float] = None,
raise_on_error: bool = False,
) -> ScanResult
Async wrapper for scan_git with cooperative native cancellation.
betterleaks_version
betterleaks_version() -> str
Return the Betterleaks version bundled into the native bridge.
raise_for_errors
raise_for_errors(result: ScanResult) -> ScanResult
Return a scan result or raise a typed exception for structured scan errors.
scan_exception_from_result
scan_exception_from_result(
result: ScanResult,
) -> ScanFailedError
Build the most specific exception for a failed scan result.