Python API
The package exposes a stable Python API for callers that want to embed the
scanner instead of shelling out. Everything in ansible_
is considered public surface and follows semantic versioning.
This page is the full reference. For day-to-day CLI usage see CLI Reference; for output shapes see Output Formats.
Quick start
Two things to notice:
scanner.returns ascan_ directory() ScanReportdataclass โ neverNone, never an exception for a clean scan. Failures during file parsing becomescan_findings inside the report rather than raised exceptions.error - Formatters expose
format(report) -> str(notformat_). The output is a fully self-contained string ready to write to a file or pipe.report
Public surface (re-exported from ansible_security_scanner )
| Symbol | Kind | What it is |
|---|---|---|
AnsibleSecurityScanner | class | The orchestrator. Constructed with scan options, returns a ScanReport from scan_. |
ScanReport, SecurityFinding, SecurityScore | dataclass | Result types. See Data models. |
MarkdownFormatter, JSONFormatter, XMLFormatter, YAMLFormatter, CSVFormatter, HTMLFormatter, JUnitFormatter, SARIFFormatter, GitLabSastFormatter, CycloneDXFormatter | class | Shipped formatters. Each is a subclass of OutputFormatter (from ansible_) with a format(report) -> str method. |
RemediationGenerator | class | Renders a per-finding remediation block. |
FixProposer | class | Generates unified-diff autofix patches for high-confidence rules (used internally when fix_). |
TaintTracker | class | Cross-file variable-flow tracker; usually constructed by the scanner, not directly. |
DependencyCollector | class | Builds the SBOM component list from requirements., meta/main., execution-environment., bindep.. |
FileScanner, VariableExtractor, ScoreCalculator | class | Lower-level building blocks; useful for custom formatters or test harnesses. |
patterns_ | module-level singleton | The pattern registry. Use patterns_ to enumerate every shipped rule grouped by category. |
parse_, setup_, get_, get_ | function | CLI helpers exposed for embedding scenarios. |
main | function | The CLI entry point as if invoked from the shell โ main([“scan”,. |
| str | The package version (PEP 440). |
Symbols that live one level deeper and are also part of the public contract:
| Import | Purpose |
|---|---|
from ansible_ | Pattern object, glob/literal rule selection, error type |
from ansible_ | Turn raw framework IDs into deep-link records |
from ansible_ | Base class for custom formatters |
AnsibleSecurityScanner
Construction options (all keyword-only after directory/target_/allowlist_/show_):
| Argument | Type | Default | Effect |
|---|---|---|---|
directory | str | ". | Scan root. Walks recursively for ., ., ., .. Dot-prefixed files are excluded unless explicitly listed in target_. |
target_ | list[str] | None | None | If set, only these paths are scanned (resolved against directory). |
allowlist_ | str | None | None | Path to allowlist YAML. See Allowlist. |
show_ | bool | False | Surface findings hidden by inline # nosec / # noqa directives. |
disable_ | bool | False | Ignore every suppression directive in the tree. Release-gate mode. |
fail_ | bool | False | Sets report. if any finding was suppressed. |
max_ | int | None | None | Sets the gate flag if more than N suppressions occurred. |
fix_ | bool | False | Attach unified-diff autofix patches to each finding’s fix_ when a rule supports it. |
scan_ | bool | False | Also scan past commits for leaked secrets. |
git_ | int | 50 | Commit horizon when scan_. |
jobs | int | 1 | Worker threads for the per-file scan pass. Findings are sorted downstream so the report is bit-for-bit equivalent regardless of jobs. |
dedup_ | bool | False | Collapse findings sharing (rule_ across files. Sibling locations are preserved on finding.. |
select_ | Iterable[str] | None | None | Whitelist of rule IDs / fnmatch globs (also accepts comma-separated strings). Unknown IDs raise RuleSelectionError at construction time. |
ignore_ | Iterable[str] | None | None | Blacklist applied after select_. Same syntax. |
scan_directory() -> ScanReport
Runs the full pipeline and returns a populated ScanReport.
Never raises for scanning errors โ file-level failures are surfaced as
synthetic scan_ findings inside the report so a single broken
playbook does not abort the whole run.
Data models
All result types are plain @dataclass instances โ they pickle, JSON-serialise
(via dataclasses.), and are safe to inspect or mutate after a scan.
ScanReport
from ansible_
| Field | Type | Notes |
|---|---|---|
scan_ | str | ISO-8601 UTC timestamp of when the scan began. |
ansible_ | str | The directory argument passed to the scanner. |
total_ | int | Count of files actually opened and scanned. |
scanned_ | list[str] | Resolved paths of every file scanned. |
findings | list[SecurityFinding] | Every finding (including synthetic ones like scan_ and cross_). Already sorted by severity then file then line. |
summary | dict[str, | Counts keyed by lowercased severity: {“critical”: int,. |
security_ | SecurityScore | Aggregate score breakdown (see below). |
suppressed_ | int | Number of findings suppressed by inline # nosec / # noqa. |
suppression_ | list[str] | Warnings about suspicious suppressions detected during the scan. |
suppressed_ | bool | True if fail_ or max_ was exceeded. |
components | list[dict[str, | Dependency inventory used by the CycloneDX SBOM formatter (Galaxy collections, roles, pip packages, bindep packages, EE base images). |
SecurityScore
from ansible_
| Field | Type | Notes |
|---|---|---|
overall_ | float | 0โ100, where 100 is clean. |
risk_ | float | 0โ100, the inverse of overall_ (higher = riskier). |
category_ | dict[str, | Per-category score (e.g. “command_, “hardcoded_). |
severity_ | dict[str, | Same shape as ScanReport. but emitted by the calculator. |
file_ | dict[str, | Per-file score keyed by resolved path. |
recommendations_ | int | Total recommendations across findings (used by Markdown/HTML reports). |
See Scoring for how the numbers are computed.
SecurityFinding
from ansible_
The richest object in the report. Core identification:
| Field | Type | Notes |
|---|---|---|
file_ | str | Relative path of the file containing the finding. |
line_ | int | 1-indexed line. 0 for findings that don’t bind to a single line (e.g. file-level metadata findings). |
rule_ | str | Stable identifier โ what select_ / ignore_ and inline # nosec rule_ match against. |
severity | str | One of “CRITICAL”, “HIGH”, “MEDIUM”, “LOW”, “INFO”. |
title | str | Short headline. |
description | str | Multi-paragraph explanation safe for Markdown rendering. |
recommendation | str | What to do about it. |
code_ | str | The matched line(s) verbatim (already redacted for credential rules). |
remediation_ | str | A correct rewrite of the snippet. |
Framework enrichment (all default to []; lists of canonical IDs that resolve
through link_):
| Field | Catalog |
|---|---|
cwe | CWE โ [“CWE-78”, |
mitre_ | MITRE ATT&CK Enterprise โ [“T1059. |
mitre_ | MITRE ATLAS (AI/ML) โ [“AML. |
cis_ | CIS Controls / Ansible Benchmark โ [“CIS-4. |
nist_ | NIST 800-53 โ [“AC-3”, |
pci_ | PCI-DSS v4 โ [“3. |
hipaa | HIPAA ยง164 โ [“164. |
soc2 | SOC 2 TSC โ [“CC6. |
stig | DISA STIG Vulnerability IDs โ [“V-230221”] |
owasp_ | OWASP Top 10 (2021/2017) โ [“A03:2021”] |
owasp_ | OWASP LLM Top 10 โ [“LLM01”] |
owasp_ | OWASP ASVS v5.0.0 โ [“V13. |
cve | CVE โ [“CVE-2024-3094”] |
Other metadata:
| Field | Type | Notes |
|---|---|---|
references | list[str] | Free-form URLs to advisories, blog posts, vendor docs. |
help_ | str | Single canonical help URL (used as SARIF helpUri). |
precision | str | SARIF precision: “very-high” | “high” | “medium” | “low”. Default “high”. |
fix_ | str | Unified-diff patch when fix_ and the rule supports autofix; "" otherwise. |
suppressed_ | str | The directive that suppressed the finding (only populated when show_). |
duplicates | list[dict] | When dedup_, sibling locations as [{“file_. |
Pattern selection
Rule selection happens in three layers, all importable from
ansible_:
known_rule_ids() -> frozenset[str]
Returns every rule ID the scanner can possibly emit โ the union of every
rule loaded from the YAML pattern files plus the synthetic IDs registered
in synthetic_ (cross_, scan_,
suspicious_).
resolve_rule_specs(specs, known_rule_ids) -> frozenset[str]
Resolves a mix of literal IDs, fnmatch globs, and comma-separated tokens
into a concrete set of matched rule IDs. Each spec is matched
independently โ a glob in one spec does not rescue a typo in
another. Unknown specs raise RuleSelectionError.
RuleSelectionError
ValueError subclass; surfaces user typos at construction time rather
than partway through a scan. The CLI maps it to exit code 2.
filter_patterns(pattern_data, *, select=None, ignore=None) -> dict[str, list[SecurityPattern]]
Pure function; never mutates its input. Useful when running the scanner internals directly:
SecurityPattern
The dataclass that backs every YAML rule. Selected fields:
| Field | Type | Notes |
|---|---|---|
id, severity, title, description, regex, recommendation, category | str | Core. |
plugin_, plugin_ | str | Pattern-file metadata. |
cwe, mitre_, mitre_, cis_, nist_, pci_, hipaa, soc2, stig, owasp_, owasp_, owasp_, cve | list[str] | Framework enrichment. |
references, help_, precision | docs hooks | |
multiline, window | bool, int | Multi-line scan window for cross-task regexes. |
positive_, negative_ | list[str] | Self-test corpus enforced by tests/test_. |
Framework deep-link resolvers
Every framework taxonomy on a finding (CWE, MITRE ATT&CK, ATLAS, CIS, NIST, PCI-DSS, HIPAA, SOC 2, STIG, OWASP App-Sec / LLM / ASVS, CVE) can be turned into a structured record with a display name and canonical URL.
The catalogs are loaded once per process from
src/ansible_. No network, no runtime
fetching.
FrameworkReference
Frozen dataclass returned by every resolver:
| Field | Type | Notes |
|---|---|---|
framework | str | Display name โ “CWE”, “MITRE ATT&CK”, “OWASP LLM Top 10”, etc. |
id | str | Canonical ID (resolvers normalise spelling โ cwe-78, CWE_, cwe 78 all collapse to CWE-78). |
name | str | Human-readable name. |
url | str | Canonical deep-link URL. |
extras | dict[str, | Catalog-specific metadata โ e.g. MITRE tactics, CIS control family. |
Single-framework resolvers
Every resolver returns FrameworkReference | None and is tolerant of
sloppy input. None means “not in the catalog”; CVE is the lone
exception โ any well-formed CVE-YYYY-NNNN synthesises a
https://nvd. reference rather than failing
closed.
resolve_all(...)
Convenience for resolving every framework on a finding in one call:
Unknown IDs are silently dropped (fail-closed). The framework-catalog
test in tests/test_ guarantees zero in-repo drops,
so a None here means the ID came from an external pattern.
known_ids() -> dict[str, frozenset]
Returns the set of catalogued IDs per framework slug (“cwe”,
“mitre_, “mitre_, “cis_, “nist_,
“pci_, “hipaa”, “soc2”, “stig”, “owasp_,
“owasp_, “owasp_, “cve”). Used by tests; useful for
building dashboards or coverage reports.
Custom formatters
Every shipped formatter extends OutputFormatter:
The contract is intentionally minimal: format(report) -> str. Anything
the formatter needs (file metadata, framework deep links, scoring
detail) it can read off the dataclass directly.
Recipe โ Slack-style summary
Recipe โ emit framework deep links per finding
CI / gating recipes
Programmatic CI gate
Everything you need to fail a CI job lives on the report. No need to shell out to the CLI โ embed the scanner and exit with the same codes the CLI uses:
Scan only changed files in a PR
parse_ accepts the noisy outputs CI tends to produce
(newline-separated git diff –name-only, space-joined env vars,
comma-joined hand input) and filters to scannable extensions:
Pick a formatter by name
The CLI’s –format flag is backed by get_, which is
also part of the public surface:
Accepted names: markdown, json, xml, yaml, csv, html,
junit, sarif, gl-sast / gitlab-sast, cyclonedx / sbom.
Unknown names raise ValueError.
Advanced recipes
Discover and introspect every shipped rule
Iterate findings with autofix patches
fix_ is a unified diff. To preview without writing, render it
with difflib. or pipe through git apply –check.
Inspect suppressions instead of silencing them
Cross-file deduplication for fork-family repos
Serialise a SecurityFinding to JSON
Findings are plain dataclasses, so dataclasses. is enough:
Drive the CLI from Python
main returns an integer exit code; it does not call sys. itself.
Versioning & stability
- Anything in
ansible_follows semver: breaking changes bump the major version.security_ scanner. all_ _ link_andresolver patterns_manager.{SecurityPattern, RuleSelectionError, resolve_rule_specs, known_rule_ids, filter_patterns}are also part of the public contract.OutputFormatter(the formatter base class) is public; adding new optional methods is non-breaking, removing any is not.- Names that start with an underscore, or live inside modules not listed
on this page (
,ast helpers playbook_, etc.), are internal and may change without notice.classifier reflects the installed package; introspect it withversion_ _ importlib.if you need it without importing.metadata. version(“ansible-security-scanner”)