All integrations

cfn-lint Integration with DefectDojo

cfn-lint Integration with DefectDojo

cfn-lint is the open source AWS CloudFormation linter, maintained in the aws-cloudformation GitHub organization. It validates CloudFormation templates in YAML or JSON against the AWS resource specification and a rule set covering correctness and best practice: invalid properties, references to attributes a resource doesn't have, unused parameters, and needless intrinsic functions. It can write results in several formats, including JSON, which is the format DefectDojo imports.

cfn-lint Integration with DefectDojo

Our infrastructure is defined in CloudFormation, and cfn-lint runs on every pull request that touches a template. Sending its output to DefectDojo gives template quality the same treatment as the rest of our findings. Each match becomes a Finding with the rule ID, file, line, and the template path to the offending property, and the stable per-match ID cfn-lint emits lets DefectDojo recognize the same problem on the next run. Warnings that sit unresolved for months are visible, and the platform team can see which stacks carry the most debt.

Why cfn-lint Matters

A CloudFormation template that is invalid fails at deploy time, often halfway through a stack update. One that is valid but sloppy makes later changes riskier.

  • cfn-lint checks templates before they reach AWS, so broken references and invalid properties are caught in review rather than during a rollout.
  • It validates against the resource specification, which keeps templates honest as resource types gain and change properties.
  • Best-practice rules flag unused parameters and needless functions that make templates harder to read and review.
  • It complements security-focused tools such as cfn-nag and CFRipper. cfn-lint tells you whether a template is correct; those tools tell you whether it is safe.

Advantages of This Integration

  • Stable identity across runs. Each cfn-lint match carries an Id that is the same when the same template is linted again and distinct within a report. DefectDojo stores it as the unique ID from tool and deduplicates on it first.
  • Grouped by rule. The rule's short description is the Finding title, so every instance of a rule groups under one heading, while the specific message naming the parameter or property opens the description.
  • Precise location. File path and line are set on every Finding, and the template path (for example Resources/ApplicationBucket/Properties/...) is included in the description, which locates nested properties better than a line number.
  • Lifecycle through reimport. Reimporting the latest results into the same Test mitigates fixed matches, adds new ones, and reactivates any that come back.
  • Tracked debt. Findings can be assigned, tagged by stack, and reported on per Asset, so template hygiene becomes measurable instead of anecdotal.

How This Integration Works

DefectDojo imports cfn-lint output with the cfn-lint Scan scan type. Only the JSON format is parsed.

1. Lint the template and save JSON.

pip install cfn-lint
cfn-lint --format json template.yaml > cfn-lint.json

cfn-lint exits non-zero when it finds anything. If your CI step fails on a non-zero exit, make sure the report upload still runs, for example in a step that executes regardless of the lint result.

2. Import the report. In the UI, open the Engagement, choose Import Scan Results, select cfn-lint Scan, and upload the file. For pipelines, use the API in Community Edition or DefectDojo Pro:

curl "https://YOUR_INSTANCE/api/v2/import-scan/" 
  -H "Authorization: Token $DD_API_TOKEN" 
  -F "scan_type=cfn-lint Scan" 
  -F "file=@cfn-lint.json" 
  -F "product_name=network-stacks" 
  -F "engagement_name=IaC Checks" 
  -F "auto_create_context=true"

DefectDojo Pro users can use Universal Importer:

universal-importer import 
  --defectdojo-url "https://YOUR_INSTANCE.cloud.defectdojo.com/" 
  --scan-type "cfn-lint Scan" 
  --report-path "./cfn-lint.json" 
  --product-name "network-stacks" 
  --engagement-name "IaC Checks" 
  --auto-create-context

3. Reimport on each merge. Send later results to /api/v2/reimport-scan/ against the same Test so the history of each template stays together.

Data Granularity: What Gets Imported

DefectDojo Field Source in cfn-lint Report Notes
Title Rule.ShortDescription Falls back to the rule ID
Severity Level Fatal to Critical, Error to High, Warning to Medium, Informational to Info; anything else Medium
Description Message, Rule.Description, rule ID, Location.Path, span, Rule.Source Message first; source links to rule documentation
File Path Filename Template that was linted
Line Location.Start.LineNumber
Vuln ID from Tool Rule.Id For example W2001
Unique ID from Tool Id Per-match and deterministic
CWE None cfn-lint reports no CWE
Finding type Static Templates are read, not deployed
Deduplication Unique ID or hash code Hash fallback uses the legacy default fields: title, cwe, line, file_path, description

The unique ID is worth trusting here. Linting the same template twice produces the same match IDs, and no two matches in one report share an ID, so the ID tracks an individual problem rather than a location. When an ID doesn't match an existing Finding, DefectDojo can still match on the hash of the fallback fields.

Use Cases

In pull request checks: A pipeline lints each changed template and reimports the results. Reviewers can see whether a change introduced new errors, and the platform team sees the backlog of existing warnings shrink or grow over time.

Across many stacks: An organization with dozens of CloudFormation repositories imports each into its own Asset. Security and platform leads get one report of template errors by team instead of reading separate CI logs.

Alongside security scanners: cfn-lint, cfn-nag, and CFRipper results for the same templates can be imported as separate Tests in one Engagement. Correctness problems and security problems stay distinct, but they live on the same Asset.

Before a migration: Teams preparing to refactor or split large stacks run cfn-lint first and use the imported Findings as a checklist of invalid or unused elements to clean up.

Operational Tips

  • Remember what the severity means. An Error means the template is invalid or will fail to deploy, and a Warning means it's valid but questionable. Neither is a security rating, so set SLAs for this scan type with that in mind.
  • If Informational matches crowd the view, use minimum_severity on import.
  • Keep file paths consistent between runs by linting from the same working directory. The file path is part of the hash used when the unique ID doesn't match.
  • Tag imports with the stack or repository name so Findings can be filtered when one Asset covers several template sets.
  • If a rule doesn't apply to a template, prefer cfn-lint's own rule configuration, or mark the Finding false positive with a note explaining why, so the decision is documented.
  • Use one Test per template set and reimport into it rather than creating a new Test on every run.