All integrations

Ansible Lint Integration with DefectDojo

Ansible Lint Integration with DefectDojo

Ansible Lint (ansible-lint) is an open source linter for Ansible playbooks, roles, and collections, maintained within the Ansible project on GitHub. It checks content against a rule set that covers correctness and idiom as well as security-relevant patterns, such as world-writable file permissions, shell use where a module exists, and certificate validation being turned off. It can write its results as Code Climate formatted JSON, which DefectDojo imports.

Ansible Lint Integration with DefectDojo

Our infrastructure is mostly Ansible, and ansible-lint already runs in the pull request checks for those repositories. The problem was that its output vanished with each build log, and nobody could tell whether the risky permission settings flagged last quarter had ever been fixed. Importing ansible-lint JSON into DefectDojo gives every violation a Finding with its rule, file, and line, keeps the rule categories so we can separate security issues from style, and lets reimports close what the team fixes.

Why Ansible Lint Matters

Ansible playbooks run with real privileges against real servers, so a sloppy task can become a security problem on every host it touches.

  • Rules like risky-file-permissions and command-instead-of-shell catch patterns that weaken hosts or make tasks harder to reason about.
  • It runs on the source, before anything is applied, which is the cheapest place to fix configuration mistakes.
  • Each rule carries categories, which lets security teams focus on the subset that matters to them.
  • Linters are noisy by nature. Without a place to triage, suppress, and track results, teams tend to ignore the output entirely.

Advantages of This Integration

  • Rule-level tracking. The rule name (check_name) is stored as the vuln ID from tool and is part of the dedupe hash, so each rule violation in each file and line is tracked on its own.
  • Security versus style. Every finding's description lists the rule's categories, so security-relevant findings can be filtered from idiom and formatting ones.
  • Reimport lifecycle. Reimporting a new report into the same Test mitigates violations that were fixed and adds new ones.
  • Direct links to rule docs. Each finding's references point to the ansible-lint documentation page for that rule.
  • Same workflow as code findings. IaC issues get SLAs, assignment, Jira pushes, and false positive handling next to the application's SAST and SCA results.

How This Integration Works

1. Generate a JSON report. Run ansible-lint with JSON output against a playbook or your project:

ansible-lint -f json playbook.yml > ansible-lint.json

ansible-lint returns a non-zero exit code when it finds violations, so make sure your pipeline step still uploads the report in that case.

Keep in mind what you are importing. ansible-lint is a general linter, not only a security scanner, and a typical first report on an older codebase is dominated by naming and idiom rules such as name[play]. That is fine, because DefectDojo keeps each rule's categories on the Finding, but it is worth deciding up front whether the security team or the platform team owns the non-security results. Many teams import everything into one Test and then build a saved filter for the security-relevant rules.

The report is a JSON array of issues. Each issue carries a rule name, categories, a severity, a description, a link to the rule's documentation, a location, and a fingerprint. An empty array (a clean run) imports zero findings.

2. Import it. In the UI, open the Engagement, choose Import Scan Results, select Ansible Lint Scan, and upload the file. For automation, use the API (Community Edition or DefectDojo Pro):

curl "https://YOUR_INSTANCE/api/v2/import-scan/" 
  -H "Authorization: Token $DD_API_TOKEN" 
  -F "scan_type=Ansible Lint Scan" 
  -F "file=@ansible-lint.json" 
  -F "product_name=infra-playbooks" 
  -F "engagement_name=CI" 
  -F "auto_create_context=true"

DefectDojo Pro users can call Universal Importer from the pipeline instead:

universal-importer import 
  --defectdojo-url "https://YOUR_INSTANCE.cloud.defectdojo.com/" 
  --scan-type "Ansible Lint Scan" 
  --report-path "./ansible-lint.json" 
  --product-name "infra-playbooks" 
  --engagement-name "CI" 
  --auto-create-context

3. Reimport on each run. For the main branch, send later reports to /api/v2/reimport-scan/ against the same Test so the open list always reflects the current code.

Data Granularity: What Gets Imported

DefectDojo Field Source in ansible-lint Report Notes
Title check_name and description Formatted as rule: description; rule name alone if no description
Severity severity blocker: Critical, critical: High, major: Medium, minor: Low, info: Info; anything else Low
Description Description, rule, categories, location Categories listed for filtering
File Path location.path Relative path in the project
Line location.positions.begin.line or location.lines.begin Both location formats handled
Vuln ID from Tool check_name The rule identifier
Unique ID from Tool fingerprint Stable per rule violation per file
References url Link to the rule's documentation
Finding type Static Source analysis
Deduplication Hashcode vuln_id_from_tool, file_path, line

Use Cases

In pull request checks: Each merge to main runs ansible-lint and reimports the report. The platform team sees new violations introduced by the change, and fixed ones close on their own.

Security-focused triage: A security engineer filters findings whose description lists security-relevant rules, such as risky file permissions or shell use, and assigns those to role owners while leaving style rules to the team's own backlog.

Shared roles across teams: An organization with a central role library imports each repository into its own Asset. When a shared role has a risky task, reporting shows every Asset that carries it.

Hardening programs: During a push to clean up legacy playbooks, the team sets an SLA for High and above and tracks burn-down in DefectDojo metrics instead of rerunning the linter and counting lines.

Operational Tips

  • ansible-lint uses the Code Climate severity scale, so critical in its output becomes High in DefectDojo, and only blocker becomes Critical.
  • Line number is part of the dedupe hash. Inserting lines above a violation can shift it and make it look new on reimport, so expect some churn after large edits.
  • Use minimum_severity to keep info and minor results out until the team has worked through the rest.
  • Use tags such as the repository or role name on import to make cross-repository filtering easy.
  • Mark style rules your team has decided not to enforce as false positives, or better, disable them in the ansible-lint configuration so they never reach DefectDojo.
  • Run ansible-lint against the same paths every time. Changing the scope between runs makes reimport mitigate findings that simply weren't scanned.