Coverity SAST: A Complete Guide for Security Testing Teams

Coverity SAST: A Complete Guide for Security Testing Teams

Static application security testing (SAST) finds vulnerabilities before your code ships. Coverity, from Synopsys, is one of the most widely deployed SAST tools in enterprise environments — used by teams that need low false-positive rates and deep language support.

This guide covers what Coverity does, how to set it up, and how QA teams get the most out of it.

What Coverity Does

Coverity analyzes source code without executing it. It builds an internal model of your program's data flows, control paths, and memory usage, then flags patterns that match known vulnerability classes.

Key capabilities:

  • Defect detection across 70+ checker categories (null pointer dereferences, buffer overflows, resource leaks, SQL injection, XSS, path traversal)
  • Interprocedural analysis — follows data across function boundaries, not just within single functions
  • Language support — C, C++, Java, C#, JavaScript, Python, Ruby, Go, Kotlin, Swift, and more
  • Low false-positive rate — Coverity is known for precision; teams typically see 15–20% false positive rates versus 50%+ from some competing tools

Architecture Overview

Coverity has two main deployment models:

Coverity Connect (on-premises): You host the analysis server. Developers submit builds from CI or locally using the cov-build capture tool. Results are uploaded to Connect for triage and reporting.

Polaris (cloud/SaaS): Synopsys's hosted platform. Connect your repo, configure a scan, and results come back via the UI or API without managing infrastructure.

For new deployments without on-prem requirements, Polaris is the simpler path.

Setting Up Coverity Analysis

On-Premises Setup

  1. Install Coverity on your analysis server (Linux recommended)
  2. Install the Coverity build tools on each developer/CI machine
  3. Configure a stream in Coverity Connect for your project

Capture a build:

cov-build --dir /tmp/cov-output make clean all
cov-analyze --dir /tmp/cov-output --all
cov-commit-defects --dir /tmp/cov-output \
  --host coverity.yourcompany.com \
  --stream my-project-main \
  --user admin

For interpreted languages (Java, Python, JavaScript), use cov-build with language-specific capture options:

# Java (Maven)
cov-build --dir /tmp/cov-output mvn compile

# JavaScript
cov-build --dir /tmp/cov-output --no-command --fs-capture-search ./src

CI/CD Integration

GitHub Actions:

- name: Coverity Scan
  run: |
    cov-build --dir cov-int make
    tar czvf myproject.tgz cov-int
    curl --form token=${{ secrets.COVERITY_TOKEN }} \
         --form email=${{ secrets.COVERITY_EMAIL }} \
         --form file=@myproject.tgz \
         --form version="$GITHUB_SHA" \
         --form description="CI build" \
         https://scan.coverity.com/builds?project=my-project

Jenkins:

stage('Coverity Scan') {
    steps {
        sh 'cov-build --dir cov-int ./build.sh'
        sh "cov-analyze --dir cov-int"
        sh "cov-commit-defects --dir cov-int --host ${COVERITY_HOST} --stream ${COVERITY_STREAM} --user ${COVERITY_USER}"
    }
}

Understanding Coverity Results

Coverity groups findings into defects — each defect has:

  • CID (Coverity Issue Defect) — unique identifier
  • Checker — the rule that fired (e.g., NULL_RETURNS, RESOURCE_LEAK, SQL_INJECTION)
  • Impact — High, Medium, Low
  • File and line — where the defect was detected
  • Events — the path Coverity traced to reach the defect

Reading the Event Trace

The event trace is Coverity's most valuable output. It shows the chain of operations that led to a vulnerability:

Event 1: user_input = request.getParameter("id")   [line 42]
Event 2: user_input passed to query()              [line 67]
Event 3: query string built with user_input        [line 89]
Event 4: SQL injection possible here               [line 89]

Follow the trace from the source (where tainted data enters) to the sink (where it's used dangerously). This tells you the actual fix needed.

Triage Workflow

Most teams set up a triage process:

  1. New defects arrive in the "Outstanding" queue after each scan
  2. Assign to owner — Coverity uses component ownership to auto-route
  3. Classify: True positive, False positive, Intentional (known safe), or Defer
  4. Fix or dismiss: True positives get bug tickets; false positives get marked dismissed with a reason

Filters that speed triage:

  • Filter by checker — work through one checker type at a time
  • Filter by impact — start with High
  • Filter by file path — assign by team/module ownership

Suppressing False Positives

In code:

// coverity[RESOURCE_LEAK]
fd = open(file, O_RDONLY);

In the UI: mark the defect as "False Positive" with a justification comment. This persists across future scans.

Key Checkers to Prioritize

Checker What It Finds
SQL_INJECTION User input reaching SQL queries unsanitized
CROSS_SITE_SCRIPTING User input reaching HTML output unsanitized
PATH_TRAVERSAL User-controlled file paths
NULL_RETURNS Dereferencing potentially null pointers
RESOURCE_LEAK File handles, sockets, memory not closed
BUFFER_OVERFLOW Array writes beyond bounds
HARDCODED_CREDENTIALS Secrets embedded in source
INSECURE_RANDOM Weak random number generation in security contexts

For web applications, prioritize the injection and XSS checkers first. For systems code (C/C++), memory safety checkers are usually more relevant.

Integrating with Issue Trackers

Coverity Connect has built-in integrations to push defects to Jira, GitHub Issues, and Azure DevOps. Configure them under Administration > Defect Tracking.

Workflow: Coverity defect → Jira issue → developer fixes → code scan confirms fix → defect closed automatically.

Metrics to Track

  • Defect density — defects per 1000 lines of code. Track over time to see if quality improves.
  • Fix rate — what percentage of flagged defects are being resolved each sprint?
  • Outstanding high-impact defects — your security backlog health indicator.
  • Scan time — as code grows, scan time grows. Monitor and optimize.

Coverity vs. Running Tests for Security

Coverity finds vulnerabilities in code paths that tests might never exercise. A unit test for your login function probably doesn't test every SQL injection variant — Coverity analyzes the data flow and flags the risk regardless of test coverage.

The tools are complementary: Coverity finds what could go wrong structurally; automated functional tests (like those you'd build with HelpMeTest) verify that the fixes actually work end-to-end without breaking existing behavior.

Common Setup Mistakes

Running analysis on non-compiled code. Coverity's C/C++ analysis requires a real compile. If cov-build doesn't see compilation commands, it won't capture anything useful.

Ignoring the event trace. Teams that just look at line numbers and checker names miss half the value. The trace tells you whether a finding is exploitable.

No baseline. Running Coverity for the first time on a legacy codebase produces thousands of findings. Set a baseline — mark everything pre-existing as "deferred" — and only triage new findings going forward.

Skipping ownership configuration. Without component ownership, all defects land in a shared queue. Nobody feels responsible. Map directories to teams.

Summary

Coverity SAST is a mature, precise static analysis tool that fits well into enterprise CI/CD pipelines. Its strengths are interprocedural analysis, low false-positive rates, and deep language support.

Start small: enable scan on your main branch, focus on High-impact findings, set up Jira integration, and build a triage habit. The value compounds as you drive defect density down over time.

Read more

Start now free