# Security Scanning > Complete guide to security scanning workflows in the StellaOps CI/CD pipeline. --- ## Security Scanning Overview StellaOps implements a **defense-in-depth** security scanning strategy: ``` ┌─────────────────────────────────────────────────────────────────┐ │ SECURITY SCANNING LAYERS │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Layer 1: PRE-COMMIT │ │ └── Secrets scanning (pre-commit hook) │ │ │ │ Layer 2: PULL REQUEST │ │ ├── SAST (Static Application Security Testing) │ │ ├── Secrets scanning │ │ ├── Dependency vulnerability audit │ │ └── License compliance check │ │ │ │ Layer 3: MAIN BRANCH │ │ ├── All Layer 2 scans │ │ ├── Container image scanning │ │ └── Extended SAST analysis │ │ │ │ Layer 4: SCHEDULED │ │ ├── Weekly deep SAST scan (Monday) │ │ ├── Weekly dependency audit (Sunday) │ │ ├── Daily container scanning │ │ └── Nightly regression security tests │ │ │ │ Layer 5: RELEASE │ │ ├── Final vulnerability gate │ │ ├── SBOM generation and signing │ │ ├── Provenance attestation │ │ └── Container signing │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## Scanning Workflows ### 1. SAST Scanning (`sast-scan.yml`) **Purpose:** Detect security vulnerabilities in source code through static analysis. **Triggers:** - Pull requests (source code changes) - Push to main/develop - Weekly Monday 3:30 AM UTC - Manual dispatch **Scanned Languages:** - C# / .NET - JavaScript / TypeScript - Python - YAML - Dockerfile **Checks Performed:** | Check | Tool | Scope | |-------|------|-------| | Code vulnerabilities | Semgrep/CodeQL (placeholder) | All source | | .NET security analyzers | Built-in Roslyn | C# code | | Dependency vulnerabilities | `dotnet list --vulnerable` | NuGet packages | | Dockerfile best practices | Hadolint | Dockerfiles | **Configuration:** ```yaml # sast-scan.yml inputs workflow_dispatch: inputs: scan_level: type: choice options: - quick # Fast scan, critical issues only - standard # Default, balanced coverage - comprehensive # Full scan, all rules fail_on_findings: type: boolean default: true # Block on findings ``` **.NET Security Analyzer Rules:** The workflow enforces these security-critical CA rules as errors: | Category | Rules | Description | |----------|-------|-------------| | SQL Injection | CA2100 | Review SQL queries for vulnerabilities | | Cryptography | CA5350-5403 | Weak crypto, insecure algorithms | | Deserialization | CA2300-2362 | Unsafe deserialization | | XML Security | CA3001-3012 | XXE, XPath injection | | Web Security | CA3061, CA5358-5398 | XSS, CSRF, CORS | --- ### 2. Secrets Scanning (`secrets-scan.yml`) **Purpose:** Detect hardcoded credentials, API keys, and secrets in code. **Triggers:** - Pull requests - Push to main/develop - Manual dispatch **Detection Patterns:** | Secret Type | Example Pattern | |-------------|-----------------| | API Keys | `sk_live_[a-zA-Z0-9]+` | | AWS Keys | `AKIA[0-9A-Z]{16}` | | Private Keys | `-----BEGIN RSA PRIVATE KEY-----` | | Connection Strings | `Password=.*;User ID=.*` | | JWT Tokens | `eyJ[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+` | | GitHub Tokens | `gh[ps]_[A-Za-z0-9]{36}` | **Tool Options (Placeholder):** ```yaml # Choose one by uncommenting in sast-scan.yml: # Option 1: TruffleHog (recommended for open source) # - name: TruffleHog Scan # uses: trufflesecurity/trufflehog@main # with: # extra_args: --only-verified # Option 2: Gitleaks # - name: Gitleaks Scan # uses: gitleaks/gitleaks-action@v2 # env: # GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} # Option 3: Semgrep # - name: Semgrep Secrets # uses: returntocorp/semgrep-action@v1 # with: # config: p/secrets ``` **Allowlist Configuration:** Create `.gitleaksignore` or `.secretsignore` for false positives: ``` # Ignore test fixtures src/__Tests/**/* docs/examples/**/* # Ignore specific files path/to/test-credentials.json # Ignore by rule ID [allowlist] regexes = ["test_api_key_[a-z]+"] ``` --- ### 3. Container Scanning (`container-scan.yml`) **Purpose:** Scan container images for OS and application vulnerabilities. **Triggers:** - Dockerfile changes - Daily schedule (4 AM UTC) - Manual dispatch **Scan Targets:** | Image | Built From | Scanned Components | |-------|------------|-------------------| | `stellaops/authority` | `src/Authority/Dockerfile` | OS packages, .NET runtime | | `stellaops/scanner` | `src/Scanner/Dockerfile` | OS packages, .NET runtime, analyzers | | `stellaops/concelier` | `src/Concelier/Dockerfile` | OS packages, .NET runtime | | (9 total images) | ... | ... | **Vulnerability Severity Levels:** | Severity | Action | Example | |----------|--------|---------| | CRITICAL | Block release | Remote code execution | | HIGH | Block release (configurable) | Privilege escalation | | MEDIUM | Warning | Information disclosure | | LOW | Log only | Minor issues | | UNKNOWN | Log only | Unclassified | **Tool Options (Placeholder):** ```yaml # Choose one by uncommenting in container-scan.yml: # Option 1: Trivy (recommended) # - name: Trivy Scan # uses: aquasecurity/trivy-action@master # with: # image-ref: ${{ steps.build.outputs.image }} # format: sarif # output: trivy-results.sarif # severity: CRITICAL,HIGH # Option 2: Grype # - name: Grype Scan # uses: anchore/scan-action@v3 # with: # image: ${{ steps.build.outputs.image }} # fail-build: true # severity-cutoff: high # Option 3: Snyk Container # - name: Snyk Container # uses: snyk/actions/docker@master # env: # SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} ``` --- ### 4. Dependency Security Scanning (`dependency-security-scan.yml`) **Purpose:** Audit NuGet and npm packages for known vulnerabilities. **Triggers:** - Weekly Sunday 2 AM UTC - Pull requests (dependency file changes) - Manual dispatch **Scanned Files:** | Ecosystem | Files | |-----------|-------| | NuGet | `src/Directory.Packages.props`, `**/*.csproj` | | npm | `**/package.json`, `**/package-lock.json` | **Vulnerability Sources:** - GitHub Advisory Database - NVD (National Vulnerability Database) - OSV (Open Source Vulnerabilities) - Vendor security advisories **Scan Process:** ``` ┌─────────────────────────────────────────────────────────────────┐ │ DEPENDENCY SECURITY SCAN │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ │ │ │ scan-nuget │ dotnet list package --vulnerable │ │ └──────┬───────┘ │ │ │ │ │ ▼ │ │ ┌──────────────┐ │ │ │ scan-npm │ npm audit --json │ │ └──────┬───────┘ │ │ │ │ │ ▼ │ │ ┌──────────────┐ │ │ │ summary │ Aggregate results, generate report │ │ └──────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` **Example Output:** ``` ## Dependency Vulnerability Audit ### NuGet Packages | Package | Installed | Vulnerable | Severity | Advisory | |---------|-----------|------------|----------|----------| | Newtonsoft.Json | 12.0.1 | < 13.0.1 | HIGH | GHSA-xxxx | ### npm Packages | Package | Installed | Vulnerable | Severity | Advisory | |---------|-----------|------------|----------|----------| | lodash | 4.17.15 | < 4.17.21 | CRITICAL | npm:lodash:1 | ``` --- ### 5. License Compliance (`dependency-license-gate.yml`) **Purpose:** Ensure all dependencies use approved licenses. **Approved Licenses:** | License | SPDX ID | Status | |---------|---------|--------| | MIT | MIT | Approved | | Apache 2.0 | Apache-2.0 | Approved | | BSD 2-Clause | BSD-2-Clause | Approved | | BSD 3-Clause | BSD-3-Clause | Approved | | ISC | ISC | Approved | | MPL 2.0 | MPL-2.0 | Review Required | | LGPL 2.1+ | LGPL-2.1-or-later | Review Required | | GPL 2.0+ | GPL-2.0-or-later | Blocked (copyleft) | | AGPL 3.0 | AGPL-3.0 | Blocked (copyleft) | **Blocked on Violation:** - GPL-licensed runtime dependencies - Unknown/proprietary licenses without explicit approval --- ## Scan Results & Reporting ### GitHub Step Summary All security scans generate GitHub Step Summary reports: ```markdown ## SAST Scan Summary | Check | Status | |-------|--------| | SAST Analysis | ✅ Pass | | .NET Security | ⚠️ 3 warnings | | Dependency Check | ✅ Pass | | Dockerfile Lint | ✅ Pass | ### .NET Security Warnings - CA5350: Weak cryptographic algorithm (src/Crypto/Legacy.cs:42) - CA2100: SQL injection risk (src/Data/Query.cs:78) ``` ### SARIF Integration Scan results are uploaded in SARIF format for IDE integration: ```yaml - name: Upload SARIF uses: github/codeql-action/upload-sarif@v3 with: sarif_file: scan-results.sarif ``` ### Artifact Retention | Artifact | Retention | |----------|-----------| | SARIF files | 30 days | | Vulnerability reports | 90 days | | License audit logs | 1 year | --- ## Security Gates ### PR Merge Requirements | Gate | Threshold | Block Merge? | |------|-----------|--------------| | SAST Critical | 0 | Yes | | SAST High | 0 | Configurable | | Secrets Found | 0 | Yes | | Vulnerable Dependencies (Critical) | 0 | Yes | | Vulnerable Dependencies (High) | 5 | Warning | | License Violations | 0 | Yes | ### Release Requirements | Gate | Threshold | Block Release? | |------|-----------|----------------| | Container Scan (Critical) | 0 | Yes | | Container Scan (High) | 0 | Yes | | SBOM Generation | Success | Yes | | Signature Verification | Valid | Yes | --- ## Remediation Workflows ### Dependency Vulnerability Fix 1. **Renovate Auto-Fix:** ```yaml # renovate.json { "vulnerabilityAlerts": { "enabled": true, "labels": ["security"], "automerge": false } } ``` 2. **Manual Override:** ```bash # Update specific package dotnet add package Newtonsoft.Json --version 13.0.3 # Audit and fix npm npm audit fix ``` ### False Positive Suppression **.NET Analyzer Suppression:** ```csharp // Suppress specific instance #pragma warning disable CA2100 // Review SQL queries for vulnerability var query = $"SELECT * FROM {tableName}"; #pragma warning restore CA2100 // Or in .editorconfig [*.cs] dotnet_diagnostic.CA2100.severity = none # NOT RECOMMENDED ``` **Semgrep/SAST Suppression:** ```csharp // nosemgrep: sql-injection var query = $"SELECT * FROM {tableName}"; ``` **Container Scan Ignore:** ```yaml # .trivyignore CVE-2021-44228 # Log4j - not applicable (no Java) CVE-2022-12345 # Accepted risk with mitigation ``` --- ## Configuration Files ### Location | File | Purpose | Location | |------|---------|----------| | `.gitleaksignore` | Secrets scan allowlist | Repository root | | `.trivyignore` | Container scan ignore list | Repository root | | `.semgrepignore` | SAST ignore patterns | Repository root | | `renovate.json` | Dependency update config | Repository root | | `.editorconfig` | Analyzer severity | Repository root | ### Example `.trivyignore` ``` # Ignore by CVE ID CVE-2021-44228 # Ignore by package pkg:npm/lodash@4.17.15 # Ignore with expiration CVE-2022-12345 exp:2025-06-01 ``` --- ## Scheduled Scan Summary | Day | Time (UTC) | Workflow | Focus | |-----|------------|----------|-------| | Daily | 2:00 AM | `nightly-regression.yml` | Security tests | | Daily | 4:00 AM | `container-scan.yml` | Image vulnerabilities | | Sunday | 2:00 AM | `dependency-security-scan.yml` | Package audit | | Monday | 3:30 AM | `sast-scan.yml` | Deep code analysis | --- ## Monitoring & Alerts ### Notification Channels Configure notifications for security findings: ```yaml # In workflow - name: Notify on Critical if: steps.scan.outputs.critical_count > 0 run: | curl -X POST "${{ secrets.SLACK_WEBHOOK }}" \ -d '{"text":"🚨 Critical security finding in '${{ github.repository }}'"}' ``` ### Dashboard Integration Security scan results can be exported to: - Grafana dashboards (via OTLP metrics) - Security Information and Event Management (SIEM) - Vulnerability management platforms --- ## Related Documentation - [README - CI/CD Overview](./README.md) - [Workflow Triggers](./workflow-triggers.md) - [Release Pipelines](./release-pipelines.md) - [Dependency Management](../operations/dependency-management.md) - [SBOM Guide](../sbom/guide.md)