Skip to main content

Configuration Files

PySentry supports TOML-based configuration files for persistent settings management.

Configuration Discovery​

Configuration files follow a hierarchical discovery pattern:

  1. Project-level (in current or parent directories, walking up to .git root):
    • .pysentry.toml (highest priority)
    • pyproject.toml [tool.pysentry] section (lower priority)
  2. User-level: ~/.config/pysentry/config.toml (Linux/macOS)
  3. System-level: /etc/pysentry/config.toml (Unix systems)

Priority: When both .pysentry.toml and pyproject.toml exist in the same directory, .pysentry.toml takes precedence.

Configuration File Example (.pysentry.toml)​

version = 1

[defaults]
format = "json"
fail_on = "high"
scope = "all"
direct_only = false
no_ci_detect = false
display = "table"
include_scripts = false

[sources]
enabled = ["pypa", "osv"]

[resolver]
type = "uv"
no_resolver = false

[cache]
enabled = true
resolution_ttl = 48
vulnerability_ttl = 48

[ignore]
ids = ["CVE-2023-12345", "GHSA-xxxx-yyyy-zzzz"]
while_no_fix = ["CVE-2025-8869"]

[maintenance]
enabled = true
forbid_archived = false
forbid_deprecated = false
forbid_quarantined = true
forbid_unmaintained = false
check_direct_only = false
cache_ttl = 1

[http]
timeout = 120
connect_timeout = 30
max_retries = 3
retry_initial_backoff = 1
retry_max_backoff = 60
show_progress = false

[output]
quiet = false

pyproject.toml Configuration​

You can configure PySentry directly in your pyproject.toml using the [tool.pysentry] section:

[project]
name = "my-project"
version = "1.0.0"

[tool.pysentry]
version = 1

[tool.pysentry.defaults]
format = "json"
fail_on = "high"
scope = "main"
direct_only = false
no_ci_detect = false
display = "table"
include_scripts = false

[tool.pysentry.sources]
enabled = ["pypa", "osv"]

[tool.pysentry.resolver]
type = "uv"
no_resolver = false

[tool.pysentry.cache]
enabled = true
resolution_ttl = 48
vulnerability_ttl = 48

[tool.pysentry.ignore]
ids = ["CVE-2023-12345"]
while_no_fix = ["CVE-2025-8869"]

[tool.pysentry.maintenance]
enabled = true
forbid_archived = false
forbid_deprecated = false
forbid_quarantined = true
forbid_unmaintained = false
check_direct_only = false
cache_ttl = 1

[tool.pysentry.http]
timeout = 120
connect_timeout = 30
max_retries = 3

[tool.pysentry.output]
quiet = false

Benefits of pyproject.toml configuration:

  • Keep all project configuration in a single file
  • No additional config files to manage
  • Works seamlessly with existing Python project tooling
  • Graceful fallback: Invalid [tool.pysentry] sections log a warning and continue to next configuration source

Configuration Sections​

[defaults]​

OptionTypeDescriptionDefault
formatstringOutput format: human, json, sarif, markdownhuman
fail_onstringMinimum severity to cause non-zero exitmedium
scopestringDependency scope: all or mainall
groupsarrayAudit only the named dependency group(s) plus main dependencies. Requires a lock file. Conflicts with scope = "main"[]
include_scriptsboolAlso scan PEP 723 Python scripts found under the project directoryfalse
direct_onlyboolOnly check direct dependenciesfalse
detailedboolEnable detailed output with full vulnerability descriptionsfalse
compactboolCompact output: summary + one-liner per vulnerability, no descriptions or fix suggestionsfalse
displaystringOutput display style for compact mode: text or tabletable
include_withdrawnboolInclude withdrawn vulnerabilities in resultsfalse
no_ci_detectboolDisable automatic CI environment detectionfalse
note

Human output is compact by default (since v0.5.0): a summary plus a one-line table row per finding (including its severity level). Set detailed = true (or pass --detailed) for full descriptions, numeric CVSS scores, and references. compact and detailed are mutually exclusive — setting both to true in your configuration file causes a validation error.

note

groups and scope = "main" cannot be used together — groups already narrows scope, and scope = "main" would strip the very groups you selected. groups also requires a group-aware lock file (uv.lock, poetry.lock, or pylock.toml, including named pylock.<name>.toml variants). See --group for the full rules.

[sources]​

OptionTypeDescriptionDefault
enabledarrayVulnerability sources to use["pypa", "pypi", "osv"]
service_urlstringOverride the OSV API base URL (custom/self-hosted OSV-compatible endpoint). Only valid when enabled is exactly ["osv"]public OSV API
fail_on_partialboolWhen a source fails but at least one succeeds, fail the run (exit 2) because the scan is incomplete. Set false (or pass --no-fail-on-partial) to continue on the sources that succeededtrue

When fail_on_partial is true (the default, fail-closed) a partial scan still prints its full findings and a partial-scan marker before exiting 2, so the incompleteness is visible. If every source fails, the run is always a hard error regardless of this setting.

[resolver]​

OptionTypeDescriptionDefault
typestringDependency resolver: uv, pip-toolsuv
no_resolverboolSkip resolver; audit only pinned (package==version) packages directly. Implies direct_onlyfalse

[cache]​

OptionTypeDescriptionDefault
enabledboolEnable cachingtrue
directorystringCustom cache directory pathPlatform-specific
resolution_ttlintResolution cache TTL in hours24
vulnerability_ttlintVulnerability cache TTL in hours48

[ignore]​

OptionTypeDescriptionDefault
idsarrayVulnerability IDs or aliases to always ignore[]
while_no_fixarrayVulnerability IDs or aliases to ignore while no fix exists[]
packagesarrayPackage names whose findings are suppressed entirely (config-only)[]

Ignore entries match the advisory's primary ID and aliases, so a CVE suppression can match a GHSA or PYSEC advisory for the same vulnerability. PySentry logs a warning when an ignore entry did not match any advisory during the run.

packages suppresses every finding for the named packages — names are compared with full PEP 503 normalization, so zope.interface, Zope_Interface, and zope-interface are equivalent. Suppressed findings are still reported (tagged as suppressed in every format) but never trigger the non-zero exit. A packages entry that matches nothing logs a warning, mirroring ids.

[ignore]
packages = ["internal-first-party-lib"]

[groups.<name>]​

Set a per-group fail_on threshold that overrides the global one for findings reaching a specific dependency group (config-only; there is no CLI flag). Requires a group-aware lock file (uv.lock, poetry.lock, or pylock.toml) — PySentry warns and ignores the thresholds otherwise.

OptionTypeDescriptionDefault
fail_onstringMinimum severity that fails the run for this group (low, medium, high, critical)global fail_on
[defaults]
fail_on = "medium" # global default

[groups.dev]
fail_on = "critical" # be lenient on dev-only dependencies

[groups.benchmark]
fail_on = "critical"

Thresholds resolve strictest-wins per context: a finding's effective threshold is the lowest (strictest) across every context that reaches it. A group-only package (never pulled into your main/production dependencies) takes its group threshold outright, so it can be looser than global — that is how [groups.dev] fail_on = "critical" lets a medium-severity dev-only advisory pass while production still fails on medium. A package that also ships to production keeps the global fail_on as a floor that a permissive group can only tighten, never loosen.

[output]​

OptionTypeDescriptionDefault
quietboolSuppress all output (equivalent to --quiet)false

[maintenance]​

OptionTypeDescriptionDefault
enabledboolEnable PEP 792 checkstrue
forbid_archivedboolFail on archived packagesfalse
forbid_deprecatedboolFail on deprecated packagesfalse
forbid_quarantinedboolFail on quarantined packagestrue
forbid_unmaintainedboolFail on any unmaintained packagesfalse
check_direct_onlyboolOnly check direct dependenciesfalse
cache_ttlintMaintenance status cache TTL in hours1

[http]​

OptionTypeDescriptionDefault
timeoutintRequest timeout in seconds120
connect_timeoutintConnection timeout in seconds30
max_retriesintMaximum retry attempts3
retry_initial_backoffintInitial retry backoff in seconds1
retry_max_backoffintMaximum retry backoff in seconds60
show_progressboolShow download progressfalse

Creating a Configuration File​

Use the built-in command to generate a configuration file:

pysentry-rs config init --output .pysentry.toml

# Generate minimal configuration
pysentry-rs config init --minimal --output .pysentry.toml

# Overwrite existing file
pysentry-rs config init --force --output .pysentry.toml

This creates a configuration file with default values that you can customize.