Skip to content

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,
)

Bases: PyBetterleaksError

Raised when a scan returns structured Betterleaks errors.

ScanConfigError

ScanConfigError(
    errors: Sequence[ScanError],
    *,
    result: Optional[ScanResult] = None,
)

Bases: ScanFailedError

Raised when Betterleaks cannot load or initialize scan configuration.

ScanTargetError

ScanTargetError(
    errors: Sequence[ScanError],
    *,
    result: Optional[ScanResult] = None,
)

Bases: ScanFailedError

Raised when the scan target is invalid or cannot be inspected.

ScanTimeoutError

ScanTimeoutError(
    errors: Sequence[ScanError],
    *,
    result: Optional[ScanResult] = None,
)

Bases: ScanFailedError

Raised when a scan times out.

UnsupportedScanError

UnsupportedScanError(
    errors: Sequence[ScanError],
    *,
    result: Optional[ScanResult] = None,
)

Bases: ScanFailedError

Raised when the native bridge reports an unsupported scan mode or scope.

InvalidScanRequestError

InvalidScanRequestError(
    errors: Sequence[ScanError],
    *,
    result: Optional[ScanResult] = None,
)

Bases: ScanFailedError

Raised when the native bridge rejects a malformed scan request.

NativeScanError

NativeScanError(
    errors: Sequence[ScanError],
    *,
    result: Optional[ScanResult] = None,
)

Bases: ScanFailedError

Raised for structured native scan failures without a more specific class.

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
)

Bases: NativeLibraryError

Raised when no bundled native library exists for the current platform.

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 config_path.

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 REDACTED.

True
timeout_seconds Optional[float]

Optional positive scan deadline in seconds.

None
raise_on_error bool

Raise a typed ScanFailedError subclass for structured scan errors.

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 timeout_seconds is not positive.

NativeLibraryError

If the native library cannot load or returns malformed data.

ScanFailedError

If raise_on_error is true and Betterleaks returns scan errors.

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 config_path.

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 REDACTED.

True
timeout_seconds Optional[float]

Optional positive scan deadline in seconds.

None
raise_on_error bool

Raise a typed ScanFailedError subclass for structured scan errors.

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 ScanError values

ScanResult

rather than raised exceptions.

Raises:

Type Description
ValueError

If timeout_seconds is not positive.

NativeLibraryError

If the native library cannot load or returns malformed data.

ScanFailedError

If raise_on_error is true and Betterleaks returns scan errors.

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".

'worktree'
config Optional[BetterleaksConfig]

Optional typed Betterleaks config. Mutually exclusive with config_path.

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 REDACTED.

True
timeout_seconds Optional[float]

Optional positive scan deadline in seconds.

None
raise_on_error bool

Raise a typed ScanFailedError subclass for structured scan errors.

False

Returns:

Type Description
ScanResult

A typed scan result. Invalid repositories are represented as structured

ScanResult

ScanError values rather than raised exceptions.

Raises:

Type Description
ValueError

If scope is unsupported or timeout_seconds is not positive.

NativeLibraryError

If the native library cannot load or returns malformed data.

ScanFailedError

If raise_on_error is true and Betterleaks returns scan errors.

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.