509 lines
15 KiB
Markdown
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)
|