Files
git.stella-ops.org/docs/cicd/security-scanning.md
StellaOps Bot e6c47c8f50 save progress
2025-12-28 23:49:56 +02:00

509 lines
15 KiB
Markdown

# 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)