BetaDeveloper

Secrets scanning

Detect hardcoded credentials before they reach a repository, an AI tool, or production. The SonarQube CLI's secrets scanning works on demand, in Git, and inside AI coding sessions.

Warning: This product is in Beta stage and we may release breaking changes.

Hardcoded credentials in source code are one of the most common and most preventable security incidents. The SonarQube CLI ships secrets scanning in three forms, each tuned for a different moment in the developer workflow:

  • Ad-hoc: sonar analyze secrets scans files or stdin from your terminal or a script.

  • Git layer: sonar integrate git installs a hook that blocks commits or pushes containing secrets.

  • AI agent layer: sonar integrate claude installs a UserPromptSubmit hook (scans the prompt you send to Claude) and a PreToolUse hook (runs before file reads/writes). sonar integrate copilot installs a pre-tool-use hook. sonar integrate codex installs a UserPromptSubmit hook for Codex, plus instructions that tell Codex to scan a file for secrets before reading it. These integrations block any operation that would expose a secret.

You can use any combination of the three.

Prerequisites

Secrets scanning runs locally on your machine. No code leaves your machine for the scan itself.

Scan on demand

sonar analyze secrets reads files (or standard input) and reports any hardcoded credentials it finds. Use it to check a file before committing, audit an .env file, or run as part of a CI step.

Scan a single file

sonar analyze secrets src/config.ts

Scan multiple paths or a directory

Scan from standard input

Use in a script

The command exits with code 51 when it finds secrets and 0 when it finds none. Wire it into any pipeline:

See Exit codes for the full table.

Block secrets at the Git layer

Install a Git hook so commits or pushes containing secrets are rejected before they reach a remote:

Pre-push hooks and global (machine-wide) installation are also supported. For setup, hook behavior with Husky and the pre-commit framework, and override options, see Git hooks.

Block secrets at the AI agent layer

When you give an AI coding assistant access to your repository, it can accidentally exfiltrate secrets by reading and including them in prompts sent to the model provider. The SonarQube CLI prevents this by installing a hook that runs before the agent reads or writes files.

After installation, restart the agent. From then on, any attempt by the agent to access a file containing a secret is blocked, and the agent is told why.

False positives and tuning

Secrets scanning is intentionally sensitive; missing a real credential is much worse than catching test fixtures. The analyzer already ignores obviously fake values, so most false positives come from test fixtures that look like real provider-issued credentials.

When that happens:

  • Keep realistic-looking test fixtures outside of source. Move them into ignored files (.env.test) or fixture directories outside src/.

  • Use environment variables in tests where possible, even when the value is a fake.

If you believe a finding is genuinely wrong, share it on the community forum; we use these reports to tune detection.

Allowlist known secrets

sonar analyze secrets can ignore a known credential, for example a test fixture that genuinely looks like a real provider-issued token. Secrets are stored as SHA-256 hashes on disk; the file lives next to the CLI binary by default and can be relocated via the SONAR_SECRETS_CACHE_DIR environment variable.

Subcommand
Description

sonar analyze secrets allowlist add [--key <key>]

Add a secret interactively or via stdin. The optional --key flag provides a human-readable identifier ([0-9a-zA-Z_-]).

sonar analyze secrets allowlist remove

Remove an entry by its key.

sonar analyze secrets allowlist show

List all allowlisted keys.

sonar analyze secrets allowlist clear

Remove all entries from the allowlist.

Surface low-confidence findings

By default the scanner silently drops candidates that look like placeholders (e.g. password, letmein) and skips files that look like tests. For benchmarking, evaluation, or to investigate why an expected secret is not reported, two flags surface these as low-confidence findings, with the filter name appended to the issue message:

Flag
Effect

--disable-entropy-filter

Low-entropy matches that would normally be silently dropped are reported as low-confidence issues. Useful for benchmark or evaluation projects.

--disable-test-file-detection

Files automatically identified as test files are no longer filtered out. Findings in those files are reported but marked as low-confidence. Has no effect on files explicitly declared as tests via the SonarQube sonar.tests property.

Custom secret rules from SonarQube Server

When the SonarQube CLI is authenticated against a SonarQube Server instance, it automatically downloads and executes custom secret rules (instances of the rule template S6784) defined on that server. Rules are cached locally and refreshed on each run. If the download fails, the SonarQube CLI falls back to a stale cache with a warning. No CLI flag is required; the feature activates automatically when the SonarQube CLI is authenticated.

Note: Custom secret rules are not yet available on SonarQube Cloud. Support is planned.

What the scanner looks for

Secrets scanning uses the same engine that powers SonarQube's server-side secret detection rules. It looks for patterns issued by major providers (AWS, GCP, GitHub, Stripe, SonarQube tokens, and many more) as well as generic high-entropy strings used in credential-shaped contexts.

Why an obvious "password" is not always reported

Secrets scanning is a layered pipeline that intentionally filters aggressively to keep false-positive rates low. Working through the layers, common reasons a hardcoded value is not reported:

  1. The file extension is in the rejected-extensions list. For example, .md, .mdx, .html, .adoc, .example, .sample, .template, .dist are skipped by every rule. This is the most likely reason.

  2. The value is a simple word (e.g. password, mypassword, 123456), rejected by the fake-password filter.

  3. The value has low entropy (e.g. letmein, abc123def), rejected by the entropy filter. Pass --disable-entropy-filter to surface it as a low-confidence finding.

  4. The file is in a docs/ or test/ directory, or is named like a test file, silently skipped by automatic test-file detection. Pass --disable-test-file-detection to surface findings in those files as low-confidence.

  5. The file extension is not in the inclusions list (and the file has no assigned language), never reached by the scanner at all.

All of these layers are intentional. The goal is to surface real, leaked credentials, not every string that looks vaguely secret-like.

Feedback

Found a false positive, a crash, or a pattern that should be detected? Tell us on the Sonar Community forum, secrets tag.

Last updated

Was this helpful?