Chapter 15Lesson 02~150 minutes

Security Hotspots, Vulnerabilities, Taint Analysis, and Review Workflow: Guided Hands-On Workflow

Run a disposable local security-analysis workflow, fix one real finding, review one hotspot-style finding using the current representation, and preserve task/revision evidence.

SecurityVulnerabilitiesHotspot reviewTaint analysisGovernance

Learning objectives

  • Create a disposable Community Build project with fake credentials and an exact revision.
  • Select current active security rules before constructing the fixture instead of assuming a historic rule classification.
  • Analyze one local vulnerability/security issue and one hotspot-style pattern without attacking any public target.
  • Fix one finding in source, reanalyze, and prove the change through task and issue evidence.
  • Review a classic hotspot when available, or document the equivalent current migrated-issue review path when it is not.
  • Revoke the project token and clean up only guarded lab resources.

1. Disposable workflow contract

Authorized local lab only. Use a local SonarQube Community Build instance and synthetic source. Do not point scanners at proprietary source for this exercise, do not probe public vulnerable targets, and never paste a real production secret into a fixture.
Item Lab value
Server SonarQube Community Build 26.9.0.129388 at http://localhost:9000
Scanner SonarScanner CLI 8.1.0.6389
Project key sq-ch15-security-lab
Language Python, chosen for a small readable fixture
Credentials Disposable project-analysis token in SONAR_TOKEN; never committed
Commercial features Not required; taint analysis is taught with a faithful local simulation/optional commercial path

2. Preflight: prove versions, project identity, and available security rules

export SONAR_HOST_URL="http://localhost:9000"
export SONAR_PROJECT_KEY="sq-ch15-security-lab"

git --version
python --version
sonar-scanner --version
curl -fsS "$SONAR_HOST_URL/api/system/status"

# In the UI, create the disposable project first, then create a project-analysis token.
# Export the token only in the current shell:
read -rsp "Disposable Sonar token: " SONAR_TOKEN; echo
export SONAR_TOKEN

# Record current security-capable Python rules before writing the fixture.
curl -fsS -H "Authorization: Bearer $SONAR_TOKEN" \
  "$SONAR_HOST_URL/api/rules/search?languages=py&ps=100" \
  > rules-python.json

Open Rules in the UI and filter the Python profile by Security impact/type. Pick one rule whose noncompliant example can be reproduced using inert local code. Separately identify a rule described as security-sensitive/hotspot-style or a rule carrying migration metadata such as former-hotspot, if your 26.9 instance exposes one.

3. Create a tiny synthetic repository

The fixture below is intentionally insecure-looking but has no listener, no database, no external network call, and no real secret. Analyzer rule availability changes, so treat these as candidate patterns; if your active rule set does not flag one, use the noncompliant example from the exact active rule you recorded in preflight.

mkdir -p sq-ch15-security-lab/src
cd sq-ch15-security-lab
git init
git config user.email "learner@example.invalid"
git config user.name "SonarQube Learner"

cat > sonar-project.properties <<'EOF'
sonar.projectKey=sq-ch15-security-lab
sonar.projectName=SQ Chapter 15 Security Lab
sonar.sources=src
sonar.sourceEncoding=UTF-8
EOF

cat > src/security_demo.py <<'PY'
import hashlib

DEMO_PASSWORD = "not-a-real-secret"

def legacy_digest(value: str) -> str:
    # Candidate security rule: weak/risky cryptographic algorithm.
    return hashlib.md5(value.encode("utf-8")).hexdigest()

def cookie_header(session_id: str) -> str:
    # Candidate hotspot-style concern: security-sensitive cookie configuration.
    return f"Set-Cookie: session={session_id}"
PY

cat > .gitignore <<'EOF'
.scannerwork/
evidence/
EOF

git add .
git commit -m "baseline insecure local fixture"
git rev-parse HEAD | tee baseline-revision.txt

4. Baseline analysis: preserve the first evidence chain

mkdir -p evidence/baseline
sonar-scanner -X 2>&1 | tee evidence/baseline/scanner.log
cp .scannerwork/report-task.txt evidence/baseline/report-task.txt

CE_TASK_ID="$(sed -n 's/^ceTaskId=//p' .scannerwork/report-task.txt)"
echo "$CE_TASK_ID" | tee evidence/baseline/ce-task-id.txt

curl -fsS -H "Authorization: Bearer $SONAR_TOKEN" \
  "$SONAR_HOST_URL/api/ce/task?id=$CE_TASK_ID" \
  | tee evidence/baseline/ce-task.json

Wait until the Compute Engine task is terminal before interpreting findings. Then record the project Issues view, security-related rule key(s), exact file/line, current issue/hotspot representation, security measures, and Quality Gate. Do not change any status yet.

5. Classify by current object, not by course vocabulary

Observed object What to preserve Action
Security issue / vulnerability Issue key, rule key, impact/type, severity, locations, history Plan a source remediation.
Classic Security Hotspot Hotspot key, rule key, review priority/status, location, review history Review context; mark safe/fixed only with evidence.
Migrated former-hotspot issue Issue key, rule key, current impact/type, migration tag/history such as former-hotspot when exposed Use current issue workflow plus a contextual review note.
No security finding Active rule inventory, profile, indexed file, scanner logs Choose another active rule’s local noncompliant example; do not claim “secure.”

6. Fix one vulnerability/security issue in source

Suppose the weak-digest candidate is actually raised by your current profile. Replace it with a stronger algorithm only for the teaching fixture. The important evidence is not the specific hash choice; it is that the exact finding disappears because the source revision changed while the profile and scope remain constant.

python - <<'PY'
from pathlib import Path
p = Path("src/security_demo.py")
text = p.read_text()
text = text.replace("hashlib.md5(value.encode(\"utf-8\")).hexdigest()",
                    "hashlib.sha256(value.encode(\"utf-8\")).hexdigest()")
p.write_text(text)
PY

git add src/security_demo.py
git commit -m "remediate security finding"
git rev-parse HEAD | tee evidence/fixed-revision.txt

mkdir -p evidence/fixed
sonar-scanner -X 2>&1 | tee evidence/fixed/scanner.log
cp .scannerwork/report-task.txt evidence/fixed/report-task.txt

Follow the new ceTaskId to completion and compare the same rule/finding. If the issue persists, preserve that fact. Do not suppress or deactivate the rule to manufacture a “fix.”

7. Review one hotspot-style pattern without gaming the result

If the instance still exposes a classic Security Hotspot for the cookie-style pattern, open it, read the rule’s risk description, identify whether the local fixture has compensating controls, and record a fake teaching-only review. Because this fixture is intentionally incomplete, the most defensible result may be Fix rather than Safe.

If the rule has already migrated to a normal issue, do not search for a nonexistent Hotspots tab. Create an evidence note instead:

finding: <issue key>
rule: <rule key>
representation: migrated security issue / former-hotspot (if exposed)
revision: <git sha>
review question: what security-sensitive behavior does the rule highlight?
context: synthetic local fixture; no production traffic or secrets
decision: fix / accepted temporarily / other current workflow state
rationale: ...
reviewer: learner@example.invalid
revisit trigger: rule/profile/product migration or code-context change

8. Optional commercial path: observe a taint flow, do not emulate licensing

If you have an authorized Developer/Enterprise/Data Center test instance with a currently supported taint-analysis language, use a tiny source-to-sink fixture and capture the flow locations. Otherwise, keep the mandatory local path: draw the expected source → propagation → sink chain manually and compare it with the product description of advanced injection-vulnerability detection.

Edition boundary. Do not install unofficial plugins or copy commercial analyzers into Community Build to imitate taint analysis. The learning goal is to understand the evidence model, not bypass licensing.

9. Challenge: choose the correct layer

After a source fix, Scanner CLI exits 0, but the security issue still appears. Which evidence do you inspect first?

  1. Confirm the Git SHA that was scanned.
  2. Confirm the file was indexed and the same rule/profile remained active.
  3. Inspect report-task.txt and Compute Engine task success.
  4. Confirm the displayed issue belongs to the new analysis/revision.
  5. Only then decide whether the remediation is technically incomplete.

Knowledge check

Your 26.9 instance has no new classic hotspot objects. Is the lab blocked?

Why should the rule/profile stay constant while proving a source remediation?

What should you do if the suggested fixture triggers no security rule?

Why is an administrator token unnecessary here?

What proves the source fix reached SonarQube?

Next lesson

Choose security-analysis and review patterns deliberately

Lesson 3 turns the workflow into durable design patterns that survive edition and taxonomy changes.

Official references and version notes

Version and compatibility note

Rechecked 2026-09-08. Mandatory examples target SonarQube Community Build 26.9.0.129388 and SonarScanner CLI 8.1.0.6389. Sonar is actively migrating Security Hotspots into ordinary security issues/vulnerabilities during 2026; classic Hotspot UI/API objects may therefore differ by rule and release, and api/hotspots is deprecated from the 2026.4 server line. The course preserves the durable contextual-review concept while requiring learners to inspect the current object representation. Current product material advertises injection-vulnerability taint analysis in Developer edition and above for selected languages (Java, C#, JavaScript/TypeScript, Python, PHP, Kotlin, Go, VB.NET); the mandatory Community Build lab uses a manual source-to-sink fallback and does not emulate commercial analyzers. Recheck rule classification, migration state, instance mode, analyzer version, and edition/language support before applying automation to another release.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.