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.
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.
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.
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.
- Scanner — a small client that runs where your code already is: a CI job, or a developer's machine. It doesn't analyze security rules deeply itself; it walks the source tree, computes raw metrics and syntax-level facts, and packages everything into a binary analysis report, which it uploads to the server and then exits. There are several scanner flavors for different build systems: the plain SonarScanner CLI, SonarScanner for Maven, SonarScanner for Gradle, and SonarScanner for .NET (
dotnet-sonarscanner, which wraps a realbegin/build/endcycle around the actual C# compiler, because C#'s analysis needs real compiler output to work from). - Web Server — the always-on process that serves the UI and the Web API, accepts uploaded analysis reports, and queues them for processing. This is also where a developer, a reviewer, or a CI job reads back results — including the Quality Gate status.
- Compute Engine — a background worker inside the server process that pulls a queued report and does the actual heavy lifting: running the language-specific rule engines against it, computing every metric, and evaluating the Quality Gate. This runs asynchronously, after the scanner has already uploaded its report and exited — which is the root cause of the single most common SonarQube CI surprise, covered in the gotchas section below.
- Database — persistent storage for everything: issues, measures, Quality Gate history, users, and Quality Profiles. Production deployments require an external database — PostgreSQL is Sonar's recommended choice, with Microsoft SQL Server and Oracle also supported; the bundled embedded H2 database is for evaluation only and is not a supported production target. Alongside it, SonarQube also runs a single-node, embedded Elasticsearch instance purely to index issues for fast search inside the UI — it isn't meant to be reachable from outside the server, and it's a common source of first-install failures on Linux, also covered below.
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" condition | Threshold (on New Code) |
|---|---|
| Coverage | < 80% fails |
| Duplicated Lines (%) | > 3% fails |
| Maintainability Rating | worse than A fails |
| Reliability Rating | worse than A fails |
| Security Rating | worse 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=300Because 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:
| Vulnerability | Security Hotspot | |
|---|---|---|
| What triggers it | The engine has high confidence the pattern is exploitable as-is | The code touches a security-sensitive API or construct whose safety depends on surrounding context the engine can't fully evaluate |
| Examples | SQL built by string concatenation reaching execute(), an eval() call fed by request input | A 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 Rating | No severity at all until reviewed — it isn't scored as a finding by itself |
| Default effect on the Quality Gate | Directly — a bad enough Security Rating on New Code fails the gate with no human step required | Indirectly, and only via the review percentage — the gate asks "was it looked at," not "was it dangerous" |
| Resolution workflow | The standard issue lifecycle: confirm, fix, or mark a documented false positive/won't-fix | A separate lifecycle: TO_REVIEW → REVIEWED, 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 respA 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."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.xmlFor 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.
| Tier | Roughly 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. |
| Developer | Multi-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. |
| Enterprise | Portfolio 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 Center | Horizontal scaling and high availability across multiple application and search nodes — an operational tier for very large installations, not new analysis capability. |
| SonarQube Cloud | The 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.
- "CE" means two different things in the same product. Compute Engine (the background analysis worker) and Community Edition (the free tier) share the same abbreviation constantly in Sonar's own docs and community forum — always read from context, and don't assume a forum post about "CE" is talking about licensing.
- The New Code period silently determines whether the gate means anything. If it's pinned to a reference branch that's gone stale, or set to a huge day-count window, "New Code" can end up meaning almost the entire codebase — or almost nothing — and a gate that seems to never catch anything, or fails constantly for reasons nobody can explain, is very often this setting, not the rules.
- Elasticsearch's bootstrap checks fail hard on a fresh Linux host. The bundled, embedded Elasticsearch node needs
vm.max_map_countraised (commonly to at least262144) and a real memory allocation; the classic first-install failure is a crypticmax virtual memory areas vm.max_map_count is too lowerror that has nothing to do with your project and everything to do with the host's kernel settings. - Unreviewed hotspots don't announce themselves the way a Vulnerability does. Because a Security Hotspot carries no severity until someone reviews it, a growing backlog doesn't show up as a wall of Critical findings — it shows up as a slowly dropping "Security Hotspots Reviewed" percentage that's easy to stop noticing until it drags a Quality Gate down.
- Forgetting
sonar.exclusionspollutes every metric at once. Vendored dependencies, generated protobuf/OpenAPI code, and build output all get analyzed by default. Unlike a SAST-only tool where that mostly means noisy findings, here it also inflates duplication and complexity metrics — a Quality Gate can fail for reasons that have nothing to do with any code your team actually wrote. - A green scanner step is not a green Quality Gate — see the dedicated warning above. This is worth repeating here because it's consistently the first surprise a team hits after their first successful-looking pipeline run.
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.
| Tool | Model | Choose it when | Costs you |
|---|---|---|---|
| SonarQube | Persistent server; SAST plus code-quality metrics under one Quality Gate; Security Hotspots for human-judgment findings | You want one governance layer for security and maintainability, with a built-in human-review lane instead of only auto-pass/auto-fail | Shallower dataflow than a security-only engine; a server and database to run and patch; free-tier feature ceilings (branching, rule depth) |
| Semgrep | Stateless CLI; per-file AST pattern matching | You want the fastest possible gate on every single commit, and are fine writing your own rules for org-specific patterns | No code-quality dimension at all; taint tracking stays within a file/project, never a whole-program model |
| CodeQL | Compiles the codebase into a queryable database; real interprocedural taint tracking | A specific service's security posture is worth a slow, deep, scheduled scan rather than a fast one on every PR | Much slower; a real query language to learn; no code-quality reporting |
| Checkmarx / Veracode / Fortify | Commercial, security-only SAST platforms with their own deep engines and enterprise workflow tooling | Security-only depth and vendor support matter more than a unified quality-plus-security dashboard | Licensing 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.
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.
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
- 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.
- 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=trueso the scanner itself polls and fails on a bad gate, or adding a separate CI step (readingreport-task.txt'sceTaskUrl) that checks the gate explicitly and is the one required in branch protection. - 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.
- 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.
- 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).