> For the complete documentation index, see [llms.txt](https://docs.sonarsource.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sonarsource.com/sonarqube-cli/analysis/sca.md).

# Software Composition Analysis (SCA)

> **Note:** SCA in the SonarQube CLI is in Beta and subject to change.

`sonar analyze dependency-risks` runs SonarQube's Software Composition Analysis (SCA) against your local project's open-source dependencies and reports the risks found: vulnerabilities, malware, and prohibited licenses. This command is in beta and subject to change. Use it after adding or updating a dependency to check it for risks before you commit.

You can also enable the same scan on a project-scoped `pre-commit` Git hook with `sonar integrate git --dependency-risks -p <project>`. See [Git hooks](/sonarqube-cli/integrations/git-hooks.md).

## Prerequisites

* [SonarQube CLI is installed and authenticated](/sonarqube-cli/quickstart-guide.md).
* A SonarQube connection where Advanced Security with SCA is enabled:
  * **SonarQube Cloud:** the organization is on a plan that includes SonarQube Advanced Security, and SCA is enabled on the project. See [Advanced Security](https://www.sonarsource.com/products/sonarqube/advanced-security/).
  * **SonarQube Server:** version 2026.4 or later, with Advanced Security licensed and SCA enabled on the project.
* The project exists on the server. `sonar analyze dependency-risks` analyzes against an existing project key. It does not create one.

> **Note:** On first use, SonarQube CLI fetches the `sca-scanner-cli` and `sonar-secrets` binaries from `binaries.sonarsource.com` and caches them under `~/.sonar/sonarqube-cli/bin/`. Subsequent runs reuse the cached binaries. To force a re-download, delete the cached file.

## Run an analysis

From the root of your project directory:

```bash
sonar analyze dependency-risks
```

SonarQube CLI auto-detects the project key from `sonar-project.properties`, SonarQube for IDE connected mode (`.sonarlint/connectedMode.json`), or the git `origin` remote when the repository is bound on SonarQube. It prints the chosen key to stderr (`Using auto-detected project key: …`). To override auto-detection, pass `--project`:

```bash
sonar analyze dependency-risks --project <YourProjectKey>
```

SonarQube CLI:

1. Resolves the project key (auto-detected or from `--project`) and verifies that your connection is authenticated and that SCA is enabled.
2. Discovers dependency manifest and lock files in your working tree and pre-scans them for hardcoded secrets. If secrets are found, the command aborts and lists each finding (file, line, and masked secret). The `sonar-secrets` binary is downloaded on first use if it is not already cached (the same binary used by `sonar analyze secrets`).
3. Downloads the `sca-scanner-cli` binary on first use, or reuses the cached copy.
4. Fetches the project's analysis settings (`sonar.exclusions`, `sonar.sca.*`) from the server.
5. Collects your dependency graph from local manifests and lock files.
6. Sends the snapshot to SonarQube for analysis.
7. Prints the unresolved dependency risks for the project.

While these steps run, progress updates print to **stderr** — for example, synchronizing settings, discovering manifests, scanning manifests for secrets, and analyzing dependency risks. In an interactive terminal you see animated spinners; in CI or other non-TTY environments you get plain one-line status messages instead. The final results always go to **stdout**, so piping `--format json` or `--format toon` into another tool won't mix progress text into the payload.

If SCA isn't enabled for the connection, the command exits immediately rather than producing empty results.

## Block risks at commit time

You can add dependency-risks scanning to your Git pre-commit hook so new risks are caught before they enter local history. Edit the hook installed by `sonar integrate git` so it calls:

```bash
sonar hook git-pre-commit --dependency-risks -p <YourProjectKey>
```

The hook runs a secrets scan on staged files first, then scans dependency manifests only when a manifest or lock file changed in the commit. It blocks the commit when new (`NEW`) risks at `MEDIUM` severity or above match the hook filter (`BLOCKER`, `HIGH`, and `MEDIUM`). Scanner or network failures fail open (the commit proceeds). Hook output is a brief summary only; run `sonar analyze dependency-risks` for the full risk table and recommendations. For setup across plain Git hooks, Husky, and the pre-commit framework, see [Git hooks](/sonarqube-cli/integrations/git-hooks.md).

## What gets analyzed

The scanner reads dependency manifests and lock files from your working tree across every ecosystem SonarQube SCA supports. For the full list of languages, package managers, and recognized manifest and lock-file names, see [Supported languages and package managers](https://docs.sonarsource.com/sonarqube-cloud/advanced-security/analyzing-projects-for-dependencies-sca/#supported-languages-and-package-managers) in the SonarQube SCA documentation. SonarQube CLI uploads those manifest and lock files to SonarQube for analysis and sends the resolved dependency snapshot derived from them; your source code stays on your machine. Run `sonar analyze dependency-risks --help` for the upload notice and supported manifest types.

SonarQube CLI applies the project's file-exclusion settings (`sonar.exclusions`, `sonar.scm.exclusions.disabled`, `sonar.sca.*`) to the snapshot before sending it. It fetches the current values from the server on each run, so changes made in the SonarQube UI take effect immediately.

> **Warning:** SonarQube CLI doesn't report issue locations for dependency risks. Each finding identifies the package and version that carries the risk, not the line where the dependency is declared. To find the manifest that pulls in a vulnerable package, use your package manager's tooling (for example, `npm ls <package>` or `mvn dependency:tree`).

## Filter by status

By default, `sonar analyze dependency-risks` shows active risks (`NEW`, `OPEN`, `CONFIRM`). Override with `--statuses`. The flag accepts presets, raw statuses, or a comma-separated mix. The result is the union, and matching is case-insensitive.

```bash
# Default: active risks only
sonar analyze dependency-risks --project my-project

# Everything, including accepted, safe, and fixed
sonar analyze dependency-risks --project my-project --statuses all

# Active risks plus accepted (waiting on a fix decision)
sonar analyze dependency-risks --project my-project --statuses to_fix

# Mix raw statuses
sonar analyze dependency-risks --project my-project --statuses new,open,confirm
```

**Presets:**

| Preset   | Expands to                                          |
| -------- | --------------------------------------------------- |
| `active` | `NEW`, `OPEN`, `CONFIRM`                            |
| `to_fix` | `NEW`, `OPEN`, `CONFIRM`, `ACCEPT`                  |
| `all`    | `NEW`, `OPEN`, `CONFIRM`, `ACCEPT`, `SAFE`, `FIXED` |

**Raw statuses:** `NEW`, `OPEN`, `CONFIRM`, `ACCEPT`, `SAFE`, `FIXED`. SonarQube CLI reports `NEW` for risks that aren't yet known to the server. The other statuses reflect the lifecycle state stored on the server.

## Filter by severity

By default, `sonar analyze dependency-risks` includes every severity. Pass `--min-severity` to exclude risks below a threshold. Allowed values are `BLOCKER`, `HIGH`, `MEDIUM`, `LOW`, and `INFO` (case-insensitive). A risk is included when its severity rank is at or above the threshold — for example, `--min-severity HIGH` returns `BLOCKER` and `HIGH` risks only.

```bash
# Only BLOCKER and HIGH risks
sonar analyze dependency-risks --project my-project --min-severity HIGH

# Combine with a status filter
sonar analyze dependency-risks --project my-project --statuses to_fix --min-severity MEDIUM
```

You can combine `--statuses` and `--min-severity`. The table summary footer shows both filters (for example, `Filtering by: new, open, confirm; severity high or above`).

## Output formats

Pass `--format` to switch between the default table output, structured JSON, and TOON for AI agents. Regardless of format, **stdout** carries only the results payload; progress and diagnostics stay on **stderr**. See [Output formats](/sonarqube-cli/using-sonarqube-cli/output-formats.md).

### Table (default)

```bash
sonar analyze dependency-risks --project my-project
```

The default `table` output groups risks by package. Each package gets a header line with its coordinates and risk count, the manifest or lock file it was found in, and one row per risk (severity, status, and a short description), followed by a per-group recommendation footer. For transitive dependencies, routes are grouped by direct parent and summarized on `via` lines (for example, `via parent@1.0.0 (← root@1.0.0) and 2 other routes`); direct dependencies are labeled `direct`. A summary footer reports the totals, the resolved filter, and any cross-package recommendations:

```
── axios@0.21.1 (1 risk) ─────────────────────────────────────────────────
in: package-lock.json

BLOCKER  OPEN     CVSS 7.5 CVE-2023-4527
Recommended versions without known vulnerabilities: 0.21.4, 0.22.0

── d3@7.0.0 (1 risk) ─────────────────────────────────────────────────────
in: package-lock.json

HIGH     OPEN     GPL-3.0
Review the license usage

════════════════════════════════════════════════════════════════════════════════

Summary: 14 dependencies checked, 3 risks found
Filtering by: new, open, confirm
```

### JSON

For AI agents and scripts:

```bash
sonar analyze dependency-risks --project my-project --format json
```

The JSON payload has the shape:

```json
{
  "project": "my-project",
  "packages": [
    {
      "package": "pkg:npm/axios@0.21.1",
      "newlyIntroduced": true,
      "riskCount": 1,
      "filePaths": ["package-lock.json"],
      "chains": [
        {
          "parentPackage": "pkg:npm/lodash@4.17.20",
          "chains": [
            ["pkg:npm/lodash@4.17.20", "pkg:npm/axios@0.21.1"]
          ]
        }
      ],
      "groups": [
        {
          "type": "VULNERABILITY",
          "totalKnownRisksCount": 1,
          "selectedRisks": [
            {
              "severity": "BLOCKER",
              "status": "OPEN",
              "vulnerabilityId": "CVE-2023-4527",
              "cvssScore": "7.5",
              "partialFixes": [
                {
                  "version": "0.21.4",
                  "descriptionCode": "NEAREST_PARTIAL",
                  "vulnerabilityIds": ["CVE-2023-4527"]
                }
              ]
            }
          ],
          "recommendation": {
            "action": "UPGRADE_PACKAGE",
            "fixVersions": [
              { "version": "0.22.0", "descriptionCode": "LATEST_STABLE", "vulnerabilityIds": [] }
            ]
          }
        }
      ]
    }
  ],
  "errors": [],
  "summary": {
    "packagesScanned": 14,
    "totalRisks": 3
  }
}
```

* Each `packages[]` entry corresponds to one analyzed dependency. The `package` field is the purl string. Additional fields include `newlyIntroduced`, `riskCount`, `filePaths` (manifests and lock files where the package appears), and `chains` (transitive routes grouped by direct parent). Each `chains[]` entry has `parentPackage` (the purl of the direct parent, or `null` when the dependency is direct) and `chains` (arrays of purls from project root to the analyzed package; multiple routes that share the same parent are grouped together).
* Each `groups[]` entry groups risks by `type` (`VULNERABILITY`, `PROHIBITED_LICENSE`, or `MALWARE`). It exposes `selectedRisks[]` (those matching your `--statuses` filter), `recommendation` (the suggested `action`, such as `UPGRADE_PACKAGE`, `REMOVE_PACKAGE`, `REVIEW_LICENSE`, or `NO_FIX_AVAILABLE`, and the `fixVersions[]` that clear every vulnerability in the group), and `totalKnownRisksCount`.
* Each risk has a `severity` (`BLOCKER`, `HIGH`, `MEDIUM`, `LOW`, or `INFO`) and a `status` (`NEW`, `OPEN`, `CONFIRM`, `ACCEPT`, `SAFE`, or `FIXED`; `NEW` is synthesized for newly introduced packages with no server-side status yet). Vulnerability risks add `vulnerabilityId`, `cvssScore` (a string, or `null`), and `partialFixes[]`. Each `partialFixes` entry clears that specific vulnerability but may leave others in the package unresolved; use `recommendation.fixVersions[]` for versions that clear every vulnerability in the group. License risks add `spdxLicenseId` and `releaseLicenseExpression` (either may be `null`).

Pipe through `jq` to flatten or filter:

```bash
sonar analyze dependency-risks --project my-project --format json \
  | jq '.packages[].groups[].selectedRisks[] | select(.severity=="BLOCKER")'
```

### TOON

For AI coding agents, prefer TOON over JSON. It carries the same dependency-risk data in a token-efficient [Token-Oriented Object Notation (TOON)](https://github.com/toon-format/toon) encoding:

```bash
sonar analyze dependency-risks --project my-project --format toon
```

TOON output mirrors the JSON structure with a few omissions tuned for LLM consumption:

* `partialFixes` on vulnerability risks are omitted
* `chains` entries summarize each direct parent as `parentPackage` (or `direct`) and `totalRoutes` instead of listing every route
* Empty `vulnerabilityIds` arrays are omitted

Use JSON when you need the full payload (for example, every transitive route or partial-fix detail). Use TOON when piping results into Claude, Copilot, or another agent.

## With an AI agent

An AI coding agent can call `sonar analyze dependency-risks` like any other shell command, read the structured output, and propose a version bump that clears the vulnerabilities. For example:

*"Run `sonar analyze dependency-risks --project my-org_my-app --format toon` and, for any BLOCKER risk, propose the smallest version bump that clears the CVE."*

## Troubleshooting

### SCA is not enabled on this connection

Your SonarQube plan or project doesn't include SonarQube Advanced Security with SCA. Confirm:

* On SonarQube Cloud, your organization is on a plan that includes Advanced Security.
* On SonarQube Server, the instance is 2026.4 or later and SCA is enabled on the project's Advanced Security configuration.

### Project not found or wrong project picked

If the CLI can't determine a project key, it exits with an error and suggests passing `--project`, adding `sonar.projectKey` to `sonar-project.properties`, or configuring a `.sonarlint/` binding.

If auto-detection picks the wrong project (for example, when your repo is mapped to several SonarQube projects), pass `--project <YourProjectKey>` explicitly.

### Authentication required

Run `sonar auth status` to inspect the active connection, and `sonar auth login` if no token is saved. See [the quickstart](/sonarqube-cli/quickstart-guide.md) for setup.

### Secrets detected in dependency manifest files

Before uploading manifests to SonarQube, the CLI scans them for hardcoded credentials. If a secret is found, the command aborts and reports the file, line, and masked value. Remove the secret from the reported file, then rerun the command. See [Secrets scanning](/sonarqube-cli/analysis/secrets-scanning.md) for general secrets-scanning guidance.

## Related pages <a href="#related-pages" id="related-pages"></a>

* [Commands reference](/sonarqube-cli/using-sonarqube-cli/commands.md)
* [Git hooks](/sonarqube-cli/integrations/git-hooks.md)
* [Analyzing local changes](/sonarqube-cli/analysis/analyzing-local-changes.md)
* [Secrets scanning](/sonarqube-cli/analysis/secrets-scanning.md)
* [Exit codes](/sonarqube-cli/using-sonarqube-cli/exit-codes.md)
* [Output formats](/sonarqube-cli/using-sonarqube-cli/output-formats.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.sonarsource.com/sonarqube-cli/analysis/sca.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
