Tools Used in DevSecOps · SonarQube

SonarQube

SonarQube is a self-hosted (or SaaS, as SonarQube Cloud) platform that runs static analysis and code-quality measurement under one roof, and enforces both through a single pass/fail mechanism called a Quality Gate. It didn't start as a security tool — it started in 2008 as "Sonar," a Java code-quality dashboard — and that ancestry is still visible in how it organizes findings: Bugs, Code Smells, and test coverage sit next to Vulnerabilities and Security Hotspots in the same project view, scored by the same gate. That's the whole pitch, and also the whole tradeoff this page works through: one governance layer for two different concerns, at the cost of a dataflow engine that's shallower than a security-only tool like CodeQL.

☺ Explain it like I'm 10

Picture a school report card that grades two completely different things on one page: how neat your handwriting is, and whether you brought anything dangerous in your backpack. Most of the backpack checks are automatic and final — a locked pocketknife bag is confiscated on sight, no debate, and that's like a SonarQube Vulnerability: found, rated, and it fails the report card by itself. But a few items aren't so clear-cut — a large pair of scissors could be for art class or could be a problem, and only a teacher looking at the actual kid, the actual class, the actual context can decide. That's a Security Hotspot: SonarQube flags it, but it doesn't fail the report card on its own — it waits for a human to look and say "safe" or "not safe." Same report card, two very different rules for the two kinds of finding.

🐢Your host for this topic: Timmy the Turtle — the Quality Gate is Timmy's favorite kind of checkpoint: it doesn't matter how the code looks or how late the release is, the gate reads the numbers and the numbers decide.

What SonarQube is, and the problem it solves

☺ Like you're 10: It's one dashboard that grades your code on two report cards at once — is it safe, and is it well-built — and refuses to let a bad enough grade on either one slip through.

SonarQube is developed by Sonar (formerly SonarSource), and it ships in two forms: a self-hosted server product — historically called SonarQube, recently reorganized under the name SonarQube Server — and a SaaS product, SonarQube Cloud (the renamed successor to SonarCloud). Both run the same underlying analysis engines and the same Quality Gate model; the difference is who operates the server and the database behind it. This page focuses on the self-hosted product, because that's the deployment shape most DevSecOps pipelines actually own and configure.

The problem it solves is consolidation. Without it, a team assembling equivalent coverage needs a linter for code smells, a coverage tool, a duplication checker, and a separate SAST engine — four tools, four dashboards, four different ideas of what "pass" means. SonarQube's Quality Gate collapses all of that into one evaluated set of conditions against one analysis, so "can this merge" is answered by one system instead of reconciling four. The cost of that consolidation is depth: because SonarQube's rule engine has to stay broad enough to cover dozens of languages and code-quality dimensions at once, its interprocedural taint tracking doesn't go nearly as deep as an engine built to do only one job, like CodeQL's whole-program relational database. SAST, DAST & SCA already named SonarQube alongside Semgrep, CodeQL, and Checkmarx as a SAST engine in the abstract; this page is what that abstraction looks like running in production.

◆ Key idea

SonarQube's whole identity is that it never asks "is this code secure" in isolation — it asks "does this analysis clear the bar we defined," where the bar can mix security, coverage, duplication, and maintainability conditions in one gate. That's exactly what makes it a governance tool as much as a scanner, and it's why the Quality Gate — not any individual rule — is the concept to understand first.

Architecture: Scanner, Web Server, Compute Engine, and the database

☺ Like you're 10: One small program runs where your code lives and reads it; a separate, always-on server does the actual thinking afterward and remembers every past result.

Unlike Semgrep's stateless, no-server CLI (see Semgrep), SonarQube is a persistent, three-tier server product, and understanding its four moving parts explains most of its operational behavior — including some of its sharpest gotchas below.

How a SonarQube analysis becomes a merge decision Scanner runs in your CI job uploads a report, exits Web Server receives the report, queues it for processing Compute Engine background worker, runs (the other "CE" — not Community Edition) Quality Gate evaluate the pass/fail conditions Database + embedded search index Postgres / SQL Server / Oracle — issues, measures, gate history Webhook fires with the gate result — nothing in CI knew the outcome before this PASS merge allowed FAIL merge blocked

Notice the gap between the scanner exiting and the webhook firing: the CI job that ran the scanner has usually already moved on to its next step by the time the Compute Engine has actually finished. That gap is deliberate architecture, not a bug — but it's also exactly the shape of the gotcha covered in the Quality Gate section next.

Quality Profiles vs. Quality Gates — the ruleset and the pass/fail line

☺ Like you're 10: One list decides which rules even apply to your code; a completely separate, shorter list decides whether today's grade is good enough to pass.

These two nouns get conflated constantly, and they answer different questions. A Quality Profile is the set of active rules for one language — hundreds of individual checks, each of which can be enabled, disabled, or have its severity adjusted. Every project is assigned one Quality Profile per language it contains (the built-in default is called "Sonar way"). A profile answers "what counts as a finding at all." A Quality Gate is a much smaller set of pass/fail conditions evaluated against the metrics an analysis produced — not a list of rules, a list of thresholds. A gate answers "given everything the profile found, does this analysis clear the bar." You tune a profile to control noise; you tune a gate to control what actually blocks a merge, and they are configured, and thought about, completely separately.

SonarQube's default gate — "Sonar way" — deliberately scopes almost every condition to the New Code period rather than the whole repository, under the philosophy Sonar calls Clean as You Code: don't demand a legacy codebase retroactively fix years of pre-existing debt before a single PR can merge, but do refuse to let today's change add to it. "New Code" itself is a configurable definition — commonly "since the previous version," a fixed number of days, or a specific reference branch — and getting that definition wrong is one of the gotchas below.

Default "Sonar way" conditionThreshold (on New Code)
Coverage< 80% fails
Duplicated Lines (%)> 3% fails
Maintainability Ratingworse than A fails
Reliability Ratingworse than A fails
Security Ratingworse than A fails
Security Hotspots Reviewed< 100% fails

Treat those exact numbers as illustrative — Sonar has adjusted default thresholds across releases, so confirm the current default against your installed version's own Quality Gate settings before you cite one on the exam or in a design review. What won't change is the shape: five of six conditions are computed automatically from the analysis, and the sixth — Security Hotspots Reviewed — is the one condition on the whole default gate that measures human attention rather than a code metric, which is the thread the next section pulls on.

# sonar-project.properties — lives at the repo root
sonar.projectKey=acme_checkout
sonar.projectName=Checkout Service
sonar.sources=src
sonar.tests=test
sonar.exclusions=**/vendor/**,**/generated/**,**/*.pb.go
sonar.coverage.exclusions=**/*_test.go,**/migrations/**
sonar.python.coverage.reportPaths=coverage.xml
sonar.host.url=${env.SONAR_HOST_URL}
sonar.token=${env.SONAR_TOKEN}
# make the SCANNER ITSELF fail (non-zero exit) if the gate fails —
# without this, the scanner step is green even on a failing gate
sonar.qualitygate.wait=true
sonar.qualitygate.timeout=300
⚠ Watch out — the scanner finishing green does not mean the gate passed

Because Quality Gate evaluation happens in the Compute Engine, asynchronously, after the scanner has already uploaded its report, a CI job that just runs sonar-scanner and checks its exit code is checking the wrong thing — a clean upload, not a clean gate. Either set sonar.qualitygate.wait=true so the scanner itself polls the Compute Engine task and fails the CI step for you, or add a dedicated gate-check step that reads report-task.txt (which the scanner writes with a ceTaskUrl) and polls the Web API separately. A pipeline missing both looks green in every log while merging code that failed its own Quality Gate.

The Security Hotspot workflow: human review, not an auto-fail

☺ Like you're 10: A Vulnerability is the engine saying "this is dangerous, full stop." A Security Hotspot is the engine saying "I found something security-sensitive here, but only a person can tell if it's actually a problem."

This is the distinction the brief for this page is really about, and it's a genuine, deliberate design choice — not a lesser or half-implemented category. SonarQube splits security findings into two kinds, and they behave completely differently:

VulnerabilitySecurity Hotspot
What triggers itThe engine has high confidence the pattern is exploitable as-isThe code touches a security-sensitive API or construct whose safety depends on surrounding context the engine can't fully evaluate
ExamplesSQL built by string concatenation reaching execute(), an eval() call fed by request inputA hardcoded IV for a cipher, a wide-open CORS policy, MD5 used for hashing, a regex that could be vulnerable to ReDoS
Severity assigned automatically?Yes — Blocker through Info, feeding straight into the Security RatingNo severity at all until reviewed — it isn't scored as a finding by itself
Default effect on the Quality GateDirectly — a bad enough Security Rating on New Code fails the gate with no human step requiredIndirectly, and only via the review percentage — the gate asks "was it looked at," not "was it dangerous"
Resolution workflowThe standard issue lifecycle: confirm, fix, or mark a documented false positive/won't-fixA separate lifecycle: TO_REVIEWREVIEWED, with a resolution of either SAFE or FIXED, and (in the UI) a comment explaining the call

The mechanism matters as much as the category label. A Vulnerability contributes to the Security Rating metric the moment analysis finishes — no human has to look at anything for a critical SQL injection finding to drag New Code's Security Rating from A to E and fail the gate outright. A Security Hotspot contributes to a completely different metric, Security Hotspots Reviewed (%), which only asks whether a person opened it and recorded a decision — reviewing a hotspot and marking it SAFE satisfies the gate exactly as well as fixing it does, because the gate's job was never to judge the hotspot itself, only to make sure it didn't get silently ignored.

# Flags as a Security Hotspot, NOT an auto-failing Vulnerability —
# a wide-open CORS policy is a real risk on some endpoints and
# a deliberate, correct choice on a genuinely public one.
@app.route("/api/public-status")
def public_status():
    resp = make_response(jsonify(status="ok"))
    resp.headers["Access-Control-Allow-Origin"] = "*"   # <- Security Hotspot
    return resp

A reviewer opens that hotspot, sees the endpoint returns nothing but a static status string with no auth context anywhere near it, and marks it Safe with a one-line comment — "public health-check endpoint, no sensitive data, intentional." That review is a permanent, auditable decision attached to that exact line, which is precisely the kind of evidence Compliance as Code at Scale covers turning into artifacts an auditor can actually read. Contrast that with the SQL-concatenation Vulnerability example this course has used repeatedly (see Static Analysis & Secrets Detection) — there is no "mark it safe" option for a Vulnerability with that shape, because the engine isn't asking for a judgment call, it's reporting one it already made.

# list open hotspots for a project via the Web API
$ curl -u "$SONAR_TOKEN:" \
    "$SONAR_HOST_URL/api/hotspots/search?projectKey=acme_checkout&status=TO_REVIEW"

# record a review decision — SAFE, with a required justification
$ curl -u "$SONAR_TOKEN:" -X POST \
    "$SONAR_HOST_URL/api/hotspots/change_status" \
    -d "hotspot=AYhk3md...&status=REVIEWED&resolution=SAFE" \
    -d "comment=Public health-check endpoint, no sensitive data, intentional."
◆ Key idea

The Quality Gate's "Security Hotspots Reviewed" condition is a forcing function for attention, not for a specific answer. It cannot be satisfied by ignoring hotspots, but it's fully satisfied by a team correctly deciding most of them are safe — which is the entire point: SonarQube isn't willing to guess about context it doesn't have, so it makes a human guess instead, and then makes sure that guess actually happened and left a paper trail.

Config, and wiring the gate into CI

☺ Like you're 10: Three files do the real work: one tells the scanner what to look at, one runs it in the pipeline, and one actually checks whether the gate passed before letting the merge through.

Beyond sonar-project.properties above, a Maven or Gradle project usually skips a standalone properties file and drives the same settings from the build tool instead, so the same values live next to everything else in the build:

<!-- pom.xml — excerpt -->
<properties>
  <sonar.projectKey>acme_checkout</sonar.projectKey>
  <sonar.coverage.jacoco.xmlReportPaths>
    target/site/jacoco/jacoco.xml
  </sonar.coverage.jacoco.xmlReportPaths>
</properties>
<!-- then: mvn verify sonar:sonar -->

A CI pipeline needs two separate steps, not one — run the scan, then separately confirm the gate, because (as the warning above covers) those two things finish at different times:

# .github/workflows/sonar.yml — illustrative; pin real action versions
# from the Marketplace rather than copying tags verbatim
jobs:
  sonar-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }   # SonarQube wants full git history, not a shallow clone
      - name: SonarQube Scan
        uses: sonarsource/sonarqube-scan-action@v2
        env:
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
      - name: Quality Gate Check
        uses: sonarsource/sonarqube-quality-gate-action@master
        timeout-minutes: 5   # polls report-task.txt's ceTaskUrl until the gate resolves
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

That second step — not the scan step — is the one branch protection should list as a required status check. A team that only requires the scan step green is exactly reproducing the gotcha from the previous section, just with an extra layer of GitHub Actions between them and the mistake.

Day-to-day commands

☺ Like you're 10: Run the scanner locally to see what it'll find before you push, then use the same API your CI uses to check or override the result by hand.

# local, exploratory run — good before opening a PR
$ sonar-scanner \
    -Dsonar.host.url=https://sonarqube.acme.internal \
    -Dsonar.token=$SONAR_TOKEN

# check a project's current Quality Gate status directly
$ curl -u "$SONAR_TOKEN:" \
    "$SONAR_HOST_URL/api/qualitygates/project_status?projectKey=acme_checkout" | jq .

# pull the raw issues list (vulnerabilities, bugs, code smells) — useful for
# feeding a triage platform like DefectDojo, or a script of your own
$ curl -u "$SONAR_TOKEN:" \
    "$SONAR_HOST_URL/api/issues/search?componentKeys=acme_checkout&types=VULNERABILITY"

# export a Quality Profile as XML — review it in a PR like any other config
$ curl -u "$SONAR_TOKEN:" \
    "$SONAR_HOST_URL/api/qualityprofiles/backup?qualityProfile=Sonar%20way&language=py" \
    -o sonar-way-python-backup.xml

For feedback earlier than any of this, SonarQube for IDE (formerly SonarLint) is the free editor plugin that runs a subset of the same rule engine locally, as you type, connected to your team's actual Quality Profile — the same "feedback in the IDE as the developer types" idea named as a top-maturity DSOMM behavior in Secure SDLC Gates & the DevSecOps Maturity Model.

Community Edition vs. the commercial tiers

☺ Like you're 10: The free version does real security and quality checking, all on its own; paying unlocks more languages of that checking, deeper analysis, and reports built for someone whose job is auditing many teams at once.

SonarQube Server ships in editions that stack: Community, Developer, Enterprise, and Data Center, each a superset of the one before it, alongside the separate SaaS product, SonarQube Cloud. Sonar has renamed and repackaged this lineup more than once — including a 2024 relicensing of Community Edition away from LGPLv3 to the Sonar Source-Available License (SSAL), which is source-available rather than an OSI-approved open-source license — so treat the table below as the shape of the offering, and confirm current names, licensing terms, and exact feature boundaries on Sonar's own edition-comparison page before it factors into a procurement or compliance decision.

TierRoughly adds
Community (self-hosted, free)The full engine covered on this page: Quality Profiles and Quality Gates, Security Hotspots, roughly twenty languages, single-branch analysis. This is a genuinely capable SAST-plus-quality tool on its own, not a crippled trial.
DeveloperMulti-branch analysis (long-lived feature branches tracked independently, not just PR snapshots), deeper taint-style dataflow rules and broader security-rule coverage for more languages, and pull request decoration on more platforms.
EnterprisePortfolio views that roll many projects' security and quality up for an executive or an auditor, compliance reports mapped to standards like OWASP Top 10 / CWE / PCI-DSS, and — as an add-on Sonar markets as "Advanced Security" — secrets detection, IaC scanning, and open-source dependency (SCA) checks layered into the same platform and the same Quality Gate.
Data CenterHorizontal scaling and high availability across multiple application and search nodes — an operational tier for very large installations, not new analysis capability.
SonarQube CloudThe SaaS product: no server to run, free for public/open-source repositories, paid for private ones, always on the current release with no upgrade cycle of your own to manage.

The practical decision most teams actually face isn't "which tier" in the abstract — it's whether Community Edition's single-branch, narrower-ruleset shape is enough for how the team actually works. A team that only ever gates pull requests against a stable default branch often never notices the branch-analysis ceiling; a team that wants long-lived feature branches independently tracked in the dashboard hits it immediately. And a team that needs secrets or IaC scanning inside the same governance layer as its code Quality Gate is shopping for Advanced Security specifically — not for SonarQube's SAST rules, which Community Edition already covers — which is worth knowing before assuming a paid upgrade is about "better security scanning" when it's really about scope of coverage.

Gotchas and failure modes

☺ Like you're 10: Most of the surprises come from SonarQube being a real server with real state, not a stateless script — timing, storage, and "did anyone actually look at it" all matter in ways a simple CLI tool never has to think about.

Alternatives and when to choose it

☺ Like you're 10: Other tools read code for danger too — the real choice is whether you want a fast single-purpose scanner, the deepest possible security analysis, or one dashboard that also grades how well the code is built.

ToolModelChoose it whenCosts you
SonarQubePersistent server; SAST plus code-quality metrics under one Quality Gate; Security Hotspots for human-judgment findingsYou want one governance layer for security and maintainability, with a built-in human-review lane instead of only auto-pass/auto-failShallower dataflow than a security-only engine; a server and database to run and patch; free-tier feature ceilings (branching, rule depth)
SemgrepStateless CLI; per-file AST pattern matchingYou want the fastest possible gate on every single commit, and are fine writing your own rules for org-specific patternsNo code-quality dimension at all; taint tracking stays within a file/project, never a whole-program model
CodeQLCompiles the codebase into a queryable database; real interprocedural taint trackingA specific service's security posture is worth a slow, deep, scheduled scan rather than a fast one on every PRMuch slower; a real query language to learn; no code-quality reporting
Checkmarx / Veracode / FortifyCommercial, security-only SAST platforms with their own deep engines and enterprise workflow toolingSecurity-only depth and vendor support matter more than a unified quality-plus-security dashboardLicensing cost at a different scale again; no built-in code-quality metrics the way SonarQube bundles them

Most mature pipelines don't pick exactly one. A common, defensible shape: Semgrep as the fastest first gate on every PR, SonarQube's Quality Gate as the merge-blocking check that also keeps maintainability and coverage from rotting, and CodeQL running on a schedule for the deep, cross-function taint tracking neither of the other two attempts. See Vulnerability Management & Triage and the DefectDojo tool page for how findings from more than one of these actually get deduplicated into a single backlog once a pipeline runs several scanners at once.

🎬 At the Shift-Left Squad
🦫

Benny: SonarQube's blocking my merge over a "Security Hotspot" on a CORS header. I checked, it's fine — it's a public status endpoint.

🐢

Timmy: A Hotspot doesn't block anything by itself. Did you actually mark it reviewed, or did you just decide it's fine in your head and move on?

🦫

Benny: ...in my head. Does that not count?

🐢

Timmy: Not to the gate. It counts reviewed hotspots, not correct opinions nobody wrote down. Open it, mark it Safe, leave the one-line reason. Then it's actually reviewed.

🦊

Foxy: Wait — so it's asking "did a human look," not "was Benny right"?

🐢

Timmy: Exactly. Compare that to the Vulnerability finding on the same build — the SQL string concatenation. Nobody gets to mark that one "safe" in their head either. That one fails the gate on its own, no review step required, because the engine's already confident it's real.

🦝

Rocky: And I'd still go check Benny's "definitely fine" endpoint myself. "In my head" is exactly the kind of gap I go looking for.

🦫

Benny: ...fair. Marking it now, with an actual reason this time.

✓ Checkpoint

1. Distinguish a Quality Profile from a Quality Gate in one sentence each. 2. Why can a CI job's scanner step finish green even when the Quality Gate ultimately fails, and what two fixes close that gap? 3. Precisely how does a Security Hotspot differ from a Vulnerability — what triggers each, and what does each one do to the Quality Gate by default? 4. What are "Compute Engine" and "Community Edition," and why does the shared abbreviation matter when reading SonarQube's own documentation? 5. Name one thing Community Edition already does on its own, and one thing that genuinely requires a paid tier.

Check your answers
  1. A Quality Profile is the set of active rules for one language — it decides what counts as a finding at all. A Quality Gate is a small set of pass/fail conditions evaluated against the metrics an analysis produced — it decides whether the result of applying those rules is good enough to pass.
  2. Because Quality Gate evaluation happens asynchronously in the Compute Engine, after the scanner has already uploaded its report and exited — the scanner's own exit code only reflects a successful upload, not the eventual gate result. The two fixes are setting sonar.qualitygate.wait=true so the scanner itself polls and fails on a bad gate, or adding a separate CI step (reading report-task.txt's ceTaskUrl) that checks the gate explicitly and is the one required in branch protection.
  3. A Vulnerability is triggered when the engine has high confidence a pattern is exploitable as-is; it's assigned a severity automatically and directly affects the Security Rating, which can fail the gate with no human involved. A Security Hotspot is triggered when code touches a security-sensitive construct whose safety depends on context the engine can't evaluate; it carries no severity until a human reviews it and marks it Safe or Fixed, and by default it only affects the gate through the separate "Security Hotspots Reviewed" percentage — a correctly-reviewed-and-marked-Safe hotspot doesn't fail anything.
  4. Compute Engine is the background worker process inside the SonarQube server that processes queued analysis reports. Community Edition is the free, self-hosted tier of the product. Both are commonly abbreviated "CE" in Sonar's own documentation and community forum, so a reference to "CE" has to be read from context — it's a real, recurring source of confusion, not a hypothetical one.
  5. Community Edition already runs the full Quality Gate/Security Hotspot model covered on this page, across roughly twenty languages, for free. Genuinely paid-tier territory includes multi-branch analysis (tracking long-lived feature branches independently, not just PR snapshots) and the Advanced Security add-on (secrets detection, IaC scanning, and SCA layered into the same platform).