All integrations

Staticcheck Integration with DefectDojo

Staticcheck Integration with DefectDojo

Staticcheck is an open source static analysis suite for Go, developed by Dominik Honnef in the go-tools project and documented at staticcheck.dev. It bundles several analyzers: the core staticcheck checks for bugs and incorrect API use, gosimple for code that can be written more simply, stylecheck for style and naming, quickfix for mechanical refactorings, and unused for dead identifiers. It prints human-readable text by default and line-delimited JSON with -f json, which is the format DefectDojo imports.

Staticcheck Integration with DefectDojo

Our Go services already run Staticcheck in CI, and DefectDojo is what turns that output into something a security team can track. A terminal full of diagnostics tells one developer what to fix right now. Imported into DefectDojo, each diagnostic becomes a Finding on the right Asset, with a severity derived from the analyzer that raised it, so a correctness bug flagged by an SA check sits in the queue at Medium while style suggestions stay at Info and out of the way. Reimporting on each build shows what was fixed and what is new, without anyone comparing two log files.

Why Staticcheck Matters

Go's compiler catches a lot, but it says nothing about misused standard library calls, impossible conditions, or code paths that can never run. Staticcheck fills that gap with checks written to report real problems rather than opinions.

  • The SA checks catch real defects: misuse of APIs, incorrect format strings, ineffective assignments, and logic that cannot do what it appears to do.
  • The unused analyzer finds dead identifiers, which keeps unreviewed code from hiding in a repository.
  • Each check has a stable code (for example SA1019 or ST1003) with a public description, so a finding can be traced to documented reasoning.
  • It runs locally and in CI with no service to host, so it fits into every pull request.

Advantages of This Integration

  • Severity that reflects the analyzer. Staticcheck has no severity scale of its own, so DefectDojo derives one from the check code prefix. SA checks import as Medium, unused (U1) as Low, and gosimple, stylecheck, and quickfix as Info. SLAs then apply to correctness bugs without style nits dragging down the numbers.
  • Build failures are visible. A compile record means a package never built and was never analyzed. DefectDojo imports it as High, so a scan that was partly blind does not look clean.
  • Suppressions carry over. When you run with -show-ignored, diagnostics silenced by a //lint:ignore directive import as Info, inactive, and marked false positive, which keeps the developer's decision on record.
  • Deduplication by check and location. Findings are hashed on the check code, file path, and line, so repeated scans of unchanged code do not create copies.
  • Reimport lifecycle. Reimporting into the same Test mitigates diagnostics that disappeared, adds new ones, and reactivates any that came back.
  • Shared workflow. Go findings get the same assignment, notes, Jira push, and reporting as findings from every other scanner on the Asset.

How This Integration Works

DefectDojo imports Staticcheck output with the Staticcheck Scan scan type.

1. Produce a JSON report. From the module root, run Staticcheck with JSON output and write it to a file:

staticcheck -f json ./... > staticcheck.json

This writes one JSON object per line rather than a single JSON document. The parser expects exactly that, so do not wrap the output in an array. Add -show-ignored if you want suppressed diagnostics recorded as false positives.

2. Import it. In the UI, open the Engagement, choose Import Scan Results, select Staticcheck Scan, and upload the file. For automation, use the API, available in Community Edition and DefectDojo Pro:

curl "https://YOUR_INSTANCE/api/v2/import-scan/" 
  -H "Authorization: Token $DD_API_TOKEN" 
  -F "scan_type=Staticcheck Scan" 
  -F "file=@staticcheck.json" 
  -F "product_name=billing-service" 
  -F "engagement_name=CI" 
  -F "auto_create_context=true"

DefectDojo Pro users can run the same import from a pipeline with Universal Importer:

universal-importer import 
  --defectdojo-url "https://YOUR_INSTANCE.cloud.defectdojo.com/" 
  --scan-type "Staticcheck Scan" 
  --report-path "./staticcheck.json" 
  --product-name "billing-service" 
  --engagement-name "CI" 
  --auto-create-context

3. Reimport on each build. For a branch you scan continuously, send later reports to /api/v2/reimport-scan/ against the same Test so resolved diagnostics are mitigated and the history stays in one place.

Data Granularity: What Gets Imported

DefectDojo Field Source in Staticcheck Report Notes
Title code and message Formatted as CODE: message
Severity Check code prefix SA is Medium, U1 is Low, S1, ST1, and QF1 are Info, unknown prefixes are Low
Severity (special cases) code and severity compile records are High; ignored diagnostics are Info
Description Message plus location details Adds check code, column, end position, and reported state
File Path location.file Path as Staticcheck reported it
Line location.line Start line of the diagnostic
Vulnerability ID from tool code For example SA4006 or ST1003
Active / False Positive severity of ignored Suppressed diagnostics import inactive and false positive
CWE Not set Staticcheck reports no CWE values
Finding type Static All findings are static
Deduplication Hashcode Vulnerability ID from tool, file path, line

Use Cases

In a CI/CD pipeline: Each merge to main runs Staticcheck and reimports into a Test per service. A release gate can query DefectDojo for active Medium or higher findings, which in practice means SA correctness checks and build failures, while style and simplification suggestions never block a release.

Across a Go monorepo: A platform team running 40 Go services imports each service into its own Asset. Security leads get one view of open correctness defects by team, and can see which services have unanalyzed packages because a compile record imported as High.

Auditing suppressions: With -show-ignored, every //lint:ignore directive becomes a false positive Finding in DefectDojo. Reviewers can filter for them and confirm that suppressed SA checks were silenced for a documented reason.

Alongside other Go tooling: Staticcheck results sit next to gosec, dependency, and container findings on the same Asset, so reporting covers the code, its modules, and its image together.

Operational Tips

  • Keep the line-delimited output exactly as Staticcheck writes it. Concatenating several runs into one file is fine, but converting it to a JSON array will break the import.
  • Treat a High compile finding as a scan problem first. Fix the build so the package is analyzed, then review what the next import reports.
  • Deduplication includes the line number, so refactoring that moves code can mitigate a finding and open an identical one a few lines away. Reimporting into the same Test keeps that churn readable.
  • Set minimum_severity=Low on import if your team does not want gosimple, stylecheck, and quickfix suggestions in DefectDojo at all.
  • Filter or report on the Vulnerability ID from tool field to track one check (for example a deprecated API check) across every repository.
  • Tag imports with the Go module or branch name so findings can be separated by release stream.