Chapter 16Lesson 02~155 minutes

Secrets, Dependency/Supply-Chain Signals, and Advanced Security Boundaries: Guided Hands-On Workflow

Run a disposable Community Build analysis with nonfunctional secret-shaped fixtures and a synthetic SARIF dependency signal, then prove which tool owns each state.

SecretsSupply chainSARIFSCA / SBOMSecurity boundaries

Learning objectives

  • Create a disposable Community Build project containing only nonfunctional secret-shaped values and synthetic dependency metadata.
  • Prove native secret-analysis scope from scanner/UI evidence before interpreting findings.
  • Generate and import a valid SARIF 2.1.0 dependency-risk signal without pretending it is native Sonar SCA.
  • Preserve revision, report path, scanner logs, ceTaskId, Compute Engine state, and native/external issue identity.
  • Map detection, inventory, remediation, rotation, and SBOM responsibilities to their owning systems.
  • Clean up the project and revoke the disposable analysis token without touching shared resources.

1. Disposable lab contract

Use only fake security data. The values below are nonfunctional teaching strings. Do not replace them with a real cloud credential, CI token, private key, production password, or customer dependency report.
Item Lab value
SonarQube Community Build 26.9.0.129388 at http://localhost:9000
Scanner SonarScanner CLI 8.1.0.6389
Project key sq-ch16-security-boundary
Source Tiny Python/config fixture + synthetic requirements.txt
Authentication Disposable project-analysis token in SONAR_TOKEN
SCA No native SCA required; synthetic external dependency issue imported through SARIF
Commercial path Optional only; no Advanced Security license is required

2. Preflight: prove environment and create the disposable project first

export SONAR_HOST_URL="http://localhost:9000"
export SONAR_PROJECT_KEY="sq-ch16-security-boundary"

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

# In the local SonarQube UI:
# 1) Create project sq-ch16-security-boundary.
# 2) Create a project-analysis token for that project.
# 3) Export it only into this shell; never commit it.
read -rsp "Disposable Sonar token: " SONAR_TOKEN; echo
export SONAR_TOKEN

Creating the project before the project-analysis token keeps the credential scope narrow. Routine analysis does not need a global administrator token.

3. Create fake-secret and dependency metadata fixtures

The AWS-looking strings below are widely used nonfunctional documentation examples and contain the word EXAMPLE. They are intentionally safe teaching material. If your current secret rules do not flag them, inspect the active Secrets rules and substitute another clearly nonfunctional pattern from the rule documentation.

mkdir -p sq-ch16-security-boundary/{src,config,reports,evidence}
cd sq-ch16-security-boundary
git init
git config user.email "learner@example.invalid"
git config user.name "SonarQube Learner"

cat > src/app.py <<'PY'
import os

def cloud_region() -> str:
    return os.environ.get("DEMO_REGION", "us-test-1")
PY

cat > config/demo.env <<'ENV'
# NONFUNCTIONAL documentation-style values for local secret-scanner training only.
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
ENV

cat > requirements.txt <<'REQ'
demo-web-framework==1.0.0
demo-parser==2.4.0
REQ

cat > sonar-project.properties <<'EOF'
sonar.projectKey=sq-ch16-security-boundary
sonar.projectName=SQ Chapter 16 Security Boundary Lab
sonar.sources=src,config,requirements.txt
sonar.sourceEncoding=UTF-8
sonar.text.inclusions=**/*.env,**/*.properties,requirements.txt
EOF

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

git add src config requirements.txt sonar-project.properties .gitignore
git commit -m "chapter16 synthetic secret and dependency fixture"
git rev-parse HEAD | tee baseline-revision.txt

4. Run 1: native Community Build analysis only

mkdir -p evidence/native
sonar-scanner -X 2>&1 | tee evidence/native/scanner.log
cp .scannerwork/report-task.txt evidence/native/report-task.txt
TASK1="$(sed -n 's/^ceTaskId=//p' .scannerwork/report-task.txt)"
echo "$TASK1" | tee evidence/native/ce-task-id.txt

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

Wait for terminal Compute Engine success before inspecting the Issues view. Record whether either synthetic value matched a currently active secret rule, the rule key, source line, issue state, and the scanner evidence that config/demo.env was included in text analysis.

Expected but not guaranteed: secret-rule inventories evolve. The learning objective is to prove the active rule/scope/result chain, not to guarantee that one historical sample always matches every future analyzer release.

5. Create a synthetic dependency-risk SARIF report

This report is deliberately fabricated and names no real CVE. Its only purpose is to exercise the ownership boundary.

cat > reports/dependency-demo.sarif <<'JSON'
{
  "version": "2.1.0",
  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
  "runs": [{
    "tool": {
      "driver": {
        "name": "SyntheticDependencyAudit",
        "version": "1.0.0",
        "rules": [{
          "id": "DEMO-DEPENDENCY-RISK-001",
          "shortDescription": {"text": "Synthetic dependency advisory"},
          "defaultConfiguration": {"level": "warning"}
        }]
      }
    },
    "results": [{
      "ruleId": "DEMO-DEPENDENCY-RISK-001",
      "level": "warning",
      "message": {"text": "Synthetic training advisory for demo-parser==2.4.0; this is not a real CVE."},
      "locations": [{
        "physicalLocation": {
          "artifactLocation": {"uri": "requirements.txt"},
          "region": {"startLine": 2}
        }
      }]
    }]
  }]
}
JSON

python -m json.tool reports/dependency-demo.sarif > /dev/null
sha256sum reports/dependency-demo.sarif | tee evidence/sarif-sha256.txt

SARIF 2.1.0 requires UTF-8 and fields such as the tool name, rule ID, and result message. The checksum becomes part of the producer evidence.

6. Run 2: import the external dependency signal at the same source revision

git rev-parse HEAD | tee evidence/import-revision.txt
mkdir -p evidence/imported
sonar-scanner -X \
  -Dsonar.sarifReportPaths=reports/dependency-demo.sarif \
  2>&1 | tee evidence/imported/scanner.log
cp .scannerwork/report-task.txt evidence/imported/report-task.txt
TASK2="$(sed -n 's/^ceTaskId=//p' .scannerwork/report-task.txt)"

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

curl -fsS -H "Authorization: Bearer $SONAR_TOKEN" \
  "$SONAR_HOST_URL/api/issues/search?componentKeys=$SONAR_PROJECT_KEY&ps=100" \
  | tee evidence/imported/issues.json

The Git SHA should match Run 1. The changed analysis input is the SARIF report path/content. After Compute Engine success, identify the external issue and prove that its rule belongs to SyntheticDependencyAudit rather than a Sonar quality profile.

7. Prove what did not happen

Observation Correct conclusion Incorrect conclusion
External dependency issue appears SARIF producer evidence was imported successfully. Community Build performed native SCA.
requirements.txt exists Dependency metadata is present in the repository. A complete transitive dependency graph exists.
No Dependencies/SBOM evidence on Community Build Native Advanced Security SCA is outside this mandatory edition. The scanner silently created an SBOM somewhere else.
Native secret issue appears A source/config pattern matched a Sonar secret rule. The owning credential has been rotated.

8. Remove the fake hard-coded secret pattern and reanalyze

cat > config/demo.env <<'ENV'
# Safe configuration contract: runtime values are injected by the environment.
AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
ENV

git add config/demo.env
git commit -m "remove synthetic hard-coded credentials"
git rev-parse HEAD | tee evidence/remediated-revision.txt

sonar-scanner -X \
  -Dsonar.sarifReportPaths=reports/dependency-demo.sarif \
  2>&1 | tee evidence/remediated-scanner.log

If a native secret issue was raised previously, correlate its post-analysis state to this new revision. Because the values were always fake, there is no real provider rotation step—but your governance note must state that a real incident would require immediate revocation/rotation before or alongside source cleanup.

9. Map each signal to its owning control

signal: native secret finding
inventory owner: SonarQube rule/profile
remediation owner: source team
real-credential lifecycle owner: external vault/provider/CI secret store
verification: source diff + provider revocation record (real incident) + reanalysis

signal: SyntheticDependencyAudit external issue
inventory/detection owner: SyntheticDependencyAudit (simulated external SCA)
remediation owner: dependency owner
SonarQube role: import/display/gate/governance surface
SBOM owner: external SCA/SBOM process unless licensed Sonar Advanced Security is actually used

10. Challenge: choose the missing layer

A team deletes a secret from Git and the Sonar issue disappears. The token was real and had been pushed to a shared remote. What must happen next?

Answer before revealing: the Git remediation proves only source state. The credential must be revoked/rotated in its issuing system, downstream consumers updated, exposure investigated, and the rotation/audit evidence retained. SonarQube cannot infer that lifecycle completion from the source diff.

Knowledge check

Why use the same Git SHA for the no-SARIF and SARIF runs?

Where is an imported SARIF rule configured?

Why are the AWS-looking strings acceptable in this lab?

If Community Build shows an imported dependency issue, what native SCA evidence should you expect?

Why keep the SARIF SHA-256?

Next lesson

Choose the right security control and ownership model

Lesson 3 compares secret, SCA/SBOM, imported-issue, and credential-management design choices.

Official references and version notes

Version and edition note

Rechecked 2026-09-08. Mandatory examples target SonarQube Community Build 26.9.0.129388 and SonarScanner CLI 8.1.0.6389. Commercial reference streams are SonarQube Server 2026 Release 4.1 and 2026.1.5 LTA. Community Build currently provides basic secrets detection and SARIF/generic external-issue import. Current product packaging expands secret coverage in commercial Server editions, while organization-specific custom secret patterns start in Enterprise edition. SonarQube Advanced Security SCA is a Server add-on starting in Enterprise edition; native dependency inventory/risk/SBOM evidence must not be claimed on Community Build merely because a manifest exists or a SARIF dependency issue was imported. Recheck secret rules, text inclusion defaults, external-report schema, supported package managers/languages, and license entitlements before automating another release.

Version and compatibility note

SonarQube product names, editions, release trains, scanner runtimes, APIs, authentication options, and platform prerequisites can change independently. Re-check the linked SonarSource primary documentation for the exact target release before applying version-sensitive commands or operational guidance outside the disposable course environment.

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.