Skip to content

SonarCloud SAST

SonarCloud provides Static Application Security Testing (SAST) and code quality analysis for every repository in the Microtec ERP platform. It is the primary tool for identifying security hotspots, code smells, and quality gate enforcement.


What Is SAST?

Static Application Security Testing analyzes source code without executing it. SonarCloud's SAST engine:

  • Detects security vulnerabilities: SQL injection, XSS, SSRF, path traversal, insecure deserialization
  • Identifies security hotspots requiring human review
  • Measures code quality: complexity, duplication, maintainability
  • Enforces coverage thresholds on new code

SAST complements DAST (Stage 13 — OWASP ZAP) which tests the running application.


Quality Gate Conditions

The Microtec SonarCloud organization has a single shared quality gate called "Microtec ERP Gate" applied to all projects.

New Code Conditions (blocks pipeline)

MetricThresholdBlocks
Coverage on new code≥ 80%Yes
Duplicated lines on new code< 3%Yes
Security hotspots reviewed100%Yes
New blocker / critical issues0Yes
New security vulnerabilities0Yes
Reliability ratingAYes
Security ratingAYes

Overall Code Conditions (informational)

MetricTargetBlocks
Maintainability ratingANo
Technical debt ratio< 5%No
Code smellsTrackedNo

Important: Only new code conditions block the pipeline. Legacy code is not penalized retroactively — this follows SonarCloud's "clean as you code" philosophy.


Multi-Language Support

SonarCloud auto-detects language from file extensions. All languages used in the Microtec platform are supported natively.

LanguageExtensionAnalysis Engine
C# (.NET 8).csRoslyn-based SonarAnalyzer
TypeScript.ts, .tsxESLint-based rules
JavaScript.js, .mjsESLint-based rules
Dart (Flutter).dartCommunity plugin
Python.pyPylint-based rules
Bicep.bicepExperimental (IaC)
XML / JSON.xml, .jsonSchema validation

.sonarcloud.properties Configuration

Each repository root contains a .sonarcloud.properties file. This file configures the SonarCloud scanner without requiring changes to the pipeline YAML.

Backend (.NET) — Platforms/.sonarcloud.properties

properties
# Project identification
sonar.projectKey=microtec_platforms
sonar.organization=microtec

# Source paths
sonar.sources=Src
sonar.tests=Src

# Exclusions — generated files, build artifacts, migrations
sonar.exclusions=\
  **/obj/**,\
  **/bin/**,\
  **/Migrations/**,\
  **/Migrations.*.cs,\
  **/*.Designer.cs,\
  **/wwwroot/**,\
  **/node_modules/**

# Test file patterns
sonar.test.inclusions=\
  **/*Tests/**,\
  **/*Test.cs,\
  **/*.Specs/**

# Coverage report path (generated by dotnet test --collect:"XPlat Code Coverage")
sonar.cs.opencover.reportsPaths=$(Agent.TempDirectory)/TestResults/**/coverage.opencover.xml

# Duplication exclusions
sonar.cpd.exclusions=\
  **/Migrations/**,\
  **/*Dto.cs,\
  **/*Request.cs,\
  **/*Response.cs

Frontend (Angular) — FrontApps/.sonarcloud.properties

properties
sonar.projectKey=microtec_frontapps
sonar.organization=microtec

sonar.sources=projects,libs
sonar.tests=projects,libs
sonar.test.inclusions=**/*.spec.ts
sonar.exclusions=\
  **/node_modules/**,\
  **/dist/**,\
  **/*.spec.ts,\
  **/*.e2e-spec.ts,\
  **/environments/**

# Coverage from Jest / Karma
sonar.javascript.lcov.reportPaths=coverage/**/lcov.info

Pipeline Integration

SonarCloud analysis runs as part of Stage 2 and uses the SonarCloud Azure DevOps service connection configured in the DevSecOps project.

yaml
# In security-pipeline-template.yml
- stage: SAST
  displayName: 'Stage 2 - SAST (SonarCloud)'
  jobs:
    - job: SonarAnalysis
      pool:
        vmImage: 'ubuntu-latest'
      steps:
        - task: SonarCloudPrepare@1
          inputs:
            SonarCloud: 'SonarCloud-ServiceConnection'
            organization: 'microtec'
            scannerMode: '$(sonarScannerMode)'   # MSBuild | CLI
            projectKey: '$(sonarProjectKey)'

        # For .NET: insert dotnet build here
        # For TypeScript: npm ci && npm test

        - task: SonarCloudAnalyze@1

        - task: SonarCloudPublish@1
          inputs:
            pollingTimeoutSec: '300'

        - task: Bash@3
          displayName: 'Check Quality Gate'
          inputs:
            script: |
              STATUS=$(curl -s -u $(SONAR_TOKEN): \
                "https://sonarcloud.io/api/qualitygates/project_status?projectKey=$(sonarProjectKey)" \
                | jq -r '.projectStatus.status')
              echo "Quality Gate: $STATUS"
              if [ "$STATUS" != "OK" ]; then exit 1; fi

Exclusions and Suppression Patterns

File-Level Exclusions

Add to .sonarcloud.properties:

properties
# Exclude auto-generated API clients
sonar.exclusions=**/MobileAPIClients/**,**/GeneratedCode/**

Issue-Level Suppression (C#)

Use [SuppressMessage] with a mandatory justification comment:

csharp
// Justified: This is a test helper, not production code
[SuppressMessage("Security", "S2068:HardcodedPassword",
    Justification = "Test fixture uses a well-known test password")]
private const string TestPassword = "TestPassword123!";

Issue-Level Suppression (TypeScript)

typescript
// NOSONAR - Justified: intentional use of any for legacy compatibility
const legacyData: any = response.data; // NOSONAR

Warning: NOSONAR suppressions are tracked by the security team and reviewed quarterly. Unjustified suppressions will be rejected in code review.


Security Hotspots vs Vulnerabilities

SonarCloud distinguishes two security finding types:

TypeMeaningAction Required
VulnerabilityConfirmed security issueFix before merge
Security HotspotPotential issue requiring reviewDeveloper must review and mark Safe/Fixed

All security hotspots on new code must be reviewed (marked Safe or Fixed) before the quality gate passes.


Viewing Results

  • SonarCloud UI: https://sonarcloud.io/project/overview?id={sonarProjectKey}
  • PR decoration: SonarCloud automatically posts inline comments on Azure DevOps PRs
  • Pipeline artifact: Quality gate JSON published under sonar-results/

Service Connection Setup

The SonarCloud-ServiceConnection is a DevOps service connection of type SonarCloud. Token is stored in Azure Key Vault mic-erp-be-dev-skv under secret SonarCloud--Token and injected as the SONAR_TOKEN pipeline variable.

Internal Documentation — Microtec Platform Team