7. CI/CD & DevSecOps¶
Verwendeter Workflow¶
GitHub Actions Pipeline¶
Datei: .github/workflows/verify.yml
Trigger: Pull Requests auf main-Branch
name: Code Quality & Security Check
on:
pull_request:
branches:
- "main"
jobs:
quality-check:
runs-on: ubuntu-latest
Workflow-Struktur¶
┌─────────────────────────────────────────┐
│ Pull Request auf main-Branch │
└─────────────────┬───────────────────┘
│
┌─────────────────▼───────────────────┐
│ GitHub Actions Workflow starten │
└─────────────────┬───────────────────┘
│
┌─────────────┼─────────────┐
│ │ │
┌───▼──────┐ ┌──▼────────┐ ┌─▼─────────┐
│ Secret │ │ Dependency│ │ Lint & │
│ Scanning │ │ Audit │ │ Type Check │
│ (Gitleaks)│ │ (npm audit)│ │ │
└───┬──────┘ └──┬────────┘ └─┬─────────┘
│ │ │
└────────────┴─────────────┘
│
┌─────────────────▼───────────────────┐
│ Backend & Frontend Tests │
│ (Jest & Vitest) │
└───────────────────────────────────┘
Services in Pipeline¶
services:
postgres:
image: postgres:16
ports:
- 5432:5432
env:
POSTGRES_USER: test_user
POSTGRES_PASSWORD: test_password
POSTGRES_DB: test_db
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
PostgreSQL wird als Container für Test-Zwecke gestartet.
Dependency Updates¶
NPM CI¶
Vorteile:
- Reproduzierbare Builds
- Schneller als
npm install - Verwendet lock-file für exakte Versionen
Overrides¶
Zweck: Erzwingt minimale Versionen für kritische Packages mit bekannten Vulnerabilities.
Frontend-Spezifisch¶
- name: Frontend Install
working-directory: ./frontend
run: |
npm ci
npm install @rollup/rollup-linux-x64-gnu --no-save --no-audit --prefer-offline
@rollup/rollup-linux-x64-gnu: Speziell für Alpine-Build (glibc vs. musl Problem).
Vulnerability Scanning¶
1. Secret Scanning (Gitleaks)¶
- name: Gitleaks Secret Scan
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Was wird gescannt:
- API-Keys
- Database-Passwords
- JWT Secrets
- SMTP-Credentials
- OAuth Client Secrets
Erkannte Patterns:
- Base64-encodierte Secrets
- URLs mit Credentials
- API-Keys von gängigen Services
- Private Keys
Pipeline-Verhalten:
- Bei gefundenen Secrets: Pipeline bricht ab (fail-fast)
- Pull Request wird blockiert
- Developer muss Secret entfernen und recommit
2. Dependency Audit (npm audit)¶
Backend:
Frontend:
Audit-Levels:
--audit-level=high: Nur kritische und high-severity--audit-level=moderate: Moderate, high, critical--audit-level=low: Alle severity levels
Beispiel-Ausgabe:
+─┬─────────────────────────────────────────────────────────────┐
│ npm audit security │
+──────────────────────────────────────────────────────────────┘┼
found 1 high severity vulnerability in node_modules/lodash
Package lodash
Patched in 4.17.21
Dependency of backend
Path backend > express > lodash
More info https://npmjs.com/advisories/1673
3. Code Quality (ESLint + TypeScript)¶
Backend:
- name: Backend Lint & Type Check
working-directory: ./backend
run: |
npx prisma generate
npm run lint
npm run typecheck
Frontend:
Was wird geprüft:
- ESLint: Code-Style, Best Practices, Anti-Patterns
- TypeScript: Typ-Korrektheit, Missing Types
- Build: Frontend-Compilierbarkeit
Automatische Tests (Frontend & Backend)¶
Backend Tests (Jest)¶
- name: Backend Tests
working-directory: ./backend
env:
DATABASE_URL: "postgresql://test_user:test_password@localhost:5432/test_db?schema=public"
run: |
echo "DATABASE_URL=postgresql://test_user:test_password@localhost:5432/test_db?schema=public" > .env
npx prisma generate
npx prisma db push --accept-data-loss
npm run test --if-present
Test-Coverage:
auth.service.test.ts: Passwort-Validierung, Hashing, Auth-Flowsecurity.test.ts: XSS-Schutz, Rate-Limiting-Konfigurationmarkdown.test.ts: Markdown-Parsing, Sanitizationnotes.service.test.ts: Notiz-CRUD, Searchindex.test.ts: API-Endpunkt-Tests
Security-Test-Beispiele:
describe("XSS Prevention", () => {
it("should sanitize script tags", () => {
const malicious = "<script>alert('xss')</script>";
const sanitized = sanitizeMarkdown(malicious);
expect(sanitized).not.toContain("<script>");
expect(sanitized).not.toContain("alert('xss')");
});
it("should sanitize onerror attributes", () => {
const malicious = '<img src="x" onerror="alert(1)">';
const sanitized = sanitizeMarkdown(malicious);
expect(sanitized).not.toContain("onerror");
});
});
describe("Password Strength Validation", () => {
it("should reject weak password with low entropy", () => {
expect(() => {
passwordService.assertStrong("password123", { userInputs: [] });
}).toThrow("WEAK_PASSWORD");
});
it("should reject password containing email", () => {
expect(() => {
passwordService.assertStrong("Example123!", {
userInputs: ["user@example.com"],
});
}).toThrow("WEAK_PASSWORD");
});
});
Frontend Tests (Vitest)¶
Test-Coverage:
api.test.ts: API-Client Tests, Error-Handlingauth-context.test.ts: Auth-Context, Token-Managementrouter.test.ts: Routing-Logik, Navigation
Frontend-Test-Beispiel:
describe("API Client", () => {
it("should automatically refresh token on 401", async () => {
// Mock original request with 401
fetchMock.mockResponseOnce(JSON.stringify({ ok: false }), { status: 401 });
// Mock refresh endpoint
fetchMock.mockResponseOnce(
JSON.stringify({ ok: true, accessToken: "new_token" })
);
// Mock second attempt (successful)
fetchMock.mockResponseOnce(JSON.stringify({ data: "success" }));
await NotesApi.list();
// Should have called refresh endpoint
expect(fetchMock).toHaveBeenCalledWith("/auth/refresh", expect.any(Object));
});
});
Sicherheitsrelevante Pipeline-Schritte¶
1. Secret Scanning (Gitleaks)¶
Purpose: Verhindert Commit von Secrets ins Repository
Configuration:
Detected Secrets:
- AWS Access Keys
- API-Keys (Stripe, GitHub, etc.)
- Database-Connection Strings
- JWT Secrets
- SMTP-Credentials
Response:
- Pipeline bricht bei gefundene Secrets
- Pull Request wird blockiert
- Developer-Benachrichtigung via GitHub
2. Dependency Audit (npm audit)¶
Purpose: Verhindert Nutzung von Dependencies mit bekannten CVEs
Configuration:
Severity Levels:
- Critical: Sofortige Gefahr, sofortiger Fix notwendig
- High: Hohe Gefahr, baldiger Fix notwendig
- Moderate: Mittlere Gefahr, geplanter Fix
- Low: Niedrige Gefahr, optionaler Fix
Pipeline-Verhalten:
- Bei High/Critical: Pipeline bricht ab
- Automatische Updates:
npm update - Manual Updates: Developer entscheidet
3. Type Checking¶
Purpose: TypeScript verhindert Type-Errors zur Kompilierzeit
Configuration:
Security-Relevanz:
- Verhindert untypisierte API-Inputs
- Erkennt fehlende Validierungen
- Stellt sicher, dass Contracts eingehalten werden
4. Security Tests¶
Purpose: Explizite Tests für Security-Szenarien
Test-Bereiche:
- XSS Prevention (Script-Tags, Event-Handler)
- SQL Injection (Parameterized Queries)
- Password Strength (zxcvbn, Patterns)
- Rate Limiting (Configuration)
- CSRF Protection (Token Validation)
Pipeline-Metriken¶
Current Status¶
| Schritt | Status | Dauer |
|---|---|---|
| Setup Node.js | ✅ | ~30s |
| Secret Scanning | ✅ | ~20s |
| Backend Install | ✅ | ~45s |
| Backend Audit | ✅ | ~10s |
| Backend Lint/TypeCheck | ✅ | ~30s |
| Backend Tests | ✅ | ~60s |
| Frontend Install | ✅ | ~45s |
| Frontend Audit | ✅ | ~10s |
| Frontend Lint/Build | ✅ | ~90s |
| Frontend Tests | ✅ | ~30s |
| Gesamt | ✅ | ~6-7 Minuten |
Success-Kriterien¶
- ✅ Alle Tests bestehen (0 failures)
- ✅ Keine Secrets gefunden (Gitleaks)
- ✅ Keine High/Critical Vulnerabilities (npm audit)
- ✅ Keine TypeScript-Errors
- ✅ Keine ESLint-Errors
Nächste Schritte¶
- Docker & Deployment - Container-Struktur und Deployment