Warum „kompiliert“ nicht „sicher“ bedeutet – OWASP & Trivy im Detail
Modul 1: Foundations & Basics | Teil 2 von 4
Von Code Sentinel, Technical Project Manager bei Java Fleet Systems Consulting
Für dich und die Java Fleet Community

📍 Deine Position in der Serie
| Modul | Teil | Thema | Status |
|---|---|---|---|
| Foundations | 1 | Erste Pipeline | ✅ Fertig |
| Foundations | → 2 | Security Gates | 👉 DU BIST HIER |
| Foundations | 3 | Coverage Gates | 🔒 Nächste Woche |
| Foundations | 4 | Quality Gates | 🔒 In 2 Wochen |
| Docker | 5-7 | Container & Registry | 🔒 Später |
| Deployment | 8-10 | Strategien & K8s | 🔒 Später |
| Enterprise | 11-12 | Advanced Patterns | 🔒 Später |
Dauer heute: 15 Minuten Lesezeit
Dein Ziel: Security-Scans in deine Pipeline einbauen
📚 Was du bisher gelernt hast
- ✅ Deine erste CI/CD Pipeline zu bauen (GitHub Actions + Jenkins)
- ✅ Automatische Builds und Tests einzurichten
- ✅ Docker-Images in der Pipeline zu erstellen
- ✅ Den Unterschied zwischen „manuell deployen“ und „Pipeline deployed“
Das Problem das übrig blieb: Deine Pipeline baut erfolgreich – aber ist der Code auch sicher?
Heute bauen wir die fehlenden Security Gates. Du wirst lernen:
- OWASP Dependency Check für Java-Dependencies
- Trivy für Container-Security
- Wie du beide in deine Pipeline integrierst
- Security-Reports richtig zu lesen und Probleme zu fixen
⚡ Was du in den nächsten 15 Minuten lernst
Nach diesem Beitrag kannst du:
- ✅ Verstehen warum 80% der Vulnerabilities aus Dependencies kommen
- ✅ OWASP Dependency Check in deine Pipeline einbauen
- ✅ Trivy für Container-Security nutzen
- ✅ Beide Tools in GitHub Actions UND Jenkins integrieren
- ✅ Security-Reports richtig lesen und Probleme fixen
Dein größter Gewinn heute: Du stoppst kritische Sicherheitslücken, bevor sie Production erreichen.
👋 Moin! Code Sentinel hier
Schön, dass du wieder dabei bist!
Erinnerst du dich? In Teil 1 haben wir deine erste Pipeline gebaut. Stefan aus Berlin hat sie direkt übernommen und war begeistert. Bis Mittwoch. Da kam die Mail vom Security-Team:
„Stefan, euer letztes Deployment hat 3 kritische CVEs nach Production gebracht. Log4j in Version 2.14.0 – das ist seit 2 Jahren bekannt. Rollback. Jetzt.“
Stefan um 17:45 Uhr:
😰 Emergency Meeting 😰 Rollback auf alte Version 😰 Dependencies durchsuchen 😰 Hotfix erstellen 😰 Incident Report schreiben 😰 Lisa wartet (schon wieder)
Und gestern kam Kofi zu mir mit genau demselben Problem. Sein Build war grün, Tests alle durch – aber Production wurde gehackt wegen einer alten Jackson-Version.
Das Problem: Die Pipeline hat gebaut, aber nicht auf Security geprüft.
Heute bauen wir das Gate, das Stefan und Kofi gebraucht hätten. Lass uns das zusammen angehen! 🛡️
🎯 Das Problem: Build ≠ Secure
Was deine Pipeline bisher macht:
✅ Code ausgecheckt ✅ Java installiert ✅ Maven Build - SUCCESS ✅ Tests laufen durch - 147 passed ✅ Docker Image gebaut ✅ Deployed to Production # Was deine Pipeline NICHT macht: ❌ Dependencies auf Vulnerabilities geprüft ❌ Container-Image gescannt ❌ Known CVEs erkannt
Das Ergebnis: Clean Build, Unsichere Production.
Mit Security Gate wäre das passiert:
✅ Code ausgecheckt
✅ Java installiert
✅ Maven Build - SUCCESS
✅ Tests laufen durch
❌ OWASP Check - FAILED!
└─ CVE-2021-44228 in log4j-core 2.14.0 (CVSS: 10.0) 🔴 CRITICAL
└─ CVE-2023-12345 in jackson-databind 2.13.0 (CVSS: 8.1) 🔴 HIGH
BUILD STOPPED ❌
Reason: Critical security vulnerabilities detected
# Du hättest sofort gesehen:
1. Welche Library ist betroffen
2. Wie kritisch ist das Problem
3. Welche Version ist sicher
4. Fix VOR Production!
Heute bauen wir genau das. Kein Deployment mehr ohne Security-Check.
🔒 Die 2 Säulen der Pipeline-Security
Warum brauchst du 2 verschiedene Tools?
OWASP Dependency Check scannt deine Java-Dependencies (pom.xml)
Trivy scannt dein Container-Image (Dockerfile + OS)
Beispiel warum du beide brauchst:
<!-- pom.xml - Sauber! -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.2.1</version> <!-- Aktuelle, sichere Version ✅ -->
</dependency>
</dependencies>
# Dockerfile - Problem!
FROM ubuntu:18.04 ← 2018er Version mit 247 Known CVEs! ❌
RUN apt-get update && \
apt-get install -y openjdk-21-jdk
COPY target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
OWASP sagt: „Java-Dependencies sind sicher ✅“
Trivy sagt: „Dein Base-Image hat 247 Sicherheitslücken ❌“
Beide zusammen = Vollständige Absicherung!
🛡️ Teil 1: OWASP Dependency Check
Was ist OWASP überhaupt?
OWASP = Open Web Application Security Project
Das ist eine gemeinnützige Organisation, die sich seit 2001 um Web-Sicherheit kümmert. Denk an OWASP wie an „Wikipedia für Security“ – nur von Experten gemacht.
Was macht OWASP?
OWASP erstellt kostenlose Tools und Guides: 📋 OWASP Top 10 → Die 10 häufigsten Web-Sicherheitslücken → Wird alle paar Jahre aktualisiert → Jeder Security-Mensch kennt die Liste 🔧 OWASP Tools (alle kostenlos!) ├─ Dependency Check ← Das nutzen wir heute! ├─ ZAP (Security Scanner) ├─ ModSecurity (Web Firewall) └─ Viele mehr... 📚 OWASP Guides ├─ Secure Coding Practices ├─ Testing Guide └─ Developer Cheat Sheets
OWASP Dependency Check ist also ein kostenloses Tool von OWASP, das deine Dependencies auf Sicherheitslücken prüft.
Was macht OWASP Dependency Check konkret?
Ein Tool, das alle deine Dependencies (auch die indirekten!) gegen die National Vulnerability Database (NVD) prüft.
Die NVD ist wie eine riesige Liste aller bekannten Sicherheitslücken weltweit:
- Über 200.000 dokumentierte CVEs (Common Vulnerabilities and Exposures)
- Täglich aktualisiert von Security-Forschern und Regierungsbehörden
- Gepflegt von der US-Regierung (NIST)
- Mit CVSS-Score (0-10) bewertet
- Kostenlos für jeden zugänglich
So funktioniert der Check:
1. OWASP liest deine pom.xml └─ Findet alle <dependency> Einträge 2. Maven löst alle transitiven Dependencies auf └─ Das sind die "Dependencies der Dependencies" 3. OWASP lädt die NVD-Datenbank herunter └─ ~500 MB mit allen bekannten Sicherheitslücken └─ Beim ersten Mal dauert das 2-5 Minuten └─ Danach nur noch Updates (30 Sekunden) 4. OWASP vergleicht JEDE Library gegen die NVD └─ "Ist spring-web 5.3.10 in der Datenbank?" └─ "Hat diese Version bekannte CVEs?" 5. Bei Match → Vulnerability gefunden! └─ OWASP berechnet CVSS-Score └─ Bei Score >= 7.0 → Build schlägt fehl └─ Report wird erstellt 6. Du siehst GENAU: ├─ Welche Library betroffen ist ├─ Welche CVE-Nummer (z.B. CVE-2021-44228) ├─ Wie kritisch (CVSS-Score) ├─ Welche Version sicher ist └─ Link zu Details
Beispiel – OWASP findet Log4Shell:
OWASP scannt deine Dependencies:
Checking: log4j-core-2.14.0.jar
├─ Searching NVD database...
├─ ❌ MATCH FOUND!
│
└─ CVE-2021-44228 (Log4Shell)
├─ CVSS Score: 10.0 (CRITICAL!)
├─ Beschreibung: Remote Code Execution möglich
├─ Betroffene Versionen: 2.0-beta9 bis 2.14.1
├─ Sichere Version: 2.17.1+
└─ Details: https://nvd.nist.gov/vuln/detail/CVE-2021-44228
BUILD FAILED ❌
Reason: Critical vulnerability detected
Kann ich OWASP auch außerhalb von CI/CD nutzen?
Ja, absolut! OWASP Dependency Check kannst du überall nutzen:
1. Lokal auf deinem Rechner (Maven):
# In deinem Projekt-Verzeichnis mvn org.owasp:dependency-check-maven:check # Das macht genau das gleiche wie in der Pipeline: # ✅ Scannt deine pom.xml # ✅ Lädt NVD-Datenbank # ✅ Erstellt Report in target/dependency-check-report.html # ✅ Öffne die HTML-Datei im Browser # Dauert beim ersten Mal 5-10 Minuten (NVD-Download) # Danach nur noch 1-2 Minuten
2. Als CLI-Tool (für beliebige Projekte):
# Download OWASP CLI wget https://github.com/jeremylong/DependencyCheck/releases/download/v9.0.0/dependency-check-9.0.0-release.zip unzip dependency-check-9.0.0-release.zip # Scanne beliebiges Verzeichnis ./dependency-check/bin/dependency-check.sh \ --scan /pfad/zu/deinem/projekt \ --format HTML \ --out report.html # Funktioniert für: # ✅ Java (Maven, Gradle) # ✅ JavaScript (npm, yarn) # ✅ Python (pip) # ✅ .NET (NuGet) # ✅ Ruby (bundler) # ✅ PHP (composer)
3. Vor dem Commit (Gute Gewohnheit!):
# BEVOR du pushst - lokaler Security-Check: git status git add . git commit -m "feat: Add new feature" # Check ERST: mvn org.owasp:dependency-check-maven:check # Wenn sauber: git push origin feature/my-branch # Wenn Findings: # → Fixe erst die Dependencies # → Dann pushen # → Pipeline wird grün bleiben
Code Sentinel’s Tipp:
„Ich nutze OWASP lokal VOR jedem Commit. Meine Regel: Wenn mein lokaler Scan rot ist, pushe ich nicht. So bleibt die Team-Pipeline grün und niemand ist sauer auf mich. 😉“
Warum kommen 80% der Sicherheitslücken aus Dependencies?
Lass mich dir das an deinem Projekt zeigen:
// DEIN Code - sagen wir 1.000 Zeilen
public class PersonService {
public Person createPerson(String name, String email) {
// Dein sicherer, geprüfter Code
if (name == null) throw new IllegalArgumentException();
return new Person(name, email);
}
}
Dein Code: 1.000 Zeilen ✅ Sauber und sicher
Aber dann schaust du in deine pom.xml:
<!-- Du schreibst: -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- Maven lädt automatisch herunter: -->
spring-boot-starter-web
├─ spring-web
├─ spring-webmvc
├─ tomcat-embed-core
├─ jackson-databind
├─ jackson-core
├─ slf4j-api
├─ logback-classic
└─ ... insgesamt 47 Libraries!
Gesamt:
- DEIN Code: 1.000 Zeilen
- FREMDER Code: 2.500.000 Zeilen (!)
Das Verhältnis: 1 zu 2.500!
Die Mathematik dahinter:
Von 100 Sicherheitslücken in einer typischen Java-App: 🔴 80 Lücken = In Dependencies (fremder Code) ├─ Log4Shell (log4j) ├─ Jackson Deserialization Bugs ├─ Spring Framework CVEs ├─ Alte Tomcat-Versionen └─ Veraltete Libraries 🟢 20 Lücken = In deinem eigenen Code ├─ SQL-Injection die DU gebaut hast ├─ XSS die DU nicht gefiltert hast └─ Deine eigenen Bugs Wo ist mehr Angriffsfläche? Im fremden Code - einfach weil da 2.500x MEHR Code ist!
Das Log4Shell-Beispiel (2021) – Die größte Java-Sicherheitslücke aller Zeiten:
Log4Shell (CVE-2021-44228) CVSS: 10.0 (Maximum! Schlimmer geht's nicht!) Wie wurde Log4Shell entdeckt? - NICHT durch OWASP! ❌ - Sondern durch einen Security-Forscher bei Alibaba - Am 24. November 2021 - Er hat Apache Foundation benachrichtigt - Öffentlich bekannt: 9. Dezember 2021 Was war das Problem? - Log4j war in ~30% ALLER Java-Apps weltweit - Die meisten wussten nicht mal, dass sie log4j nutzen - Es kam über transitive Dependencies rein - Angreifer konnten JEDEN Server übernehmen - Mit einem einzigen HTTP-Request! Betroffene Firmen: - Apple, Tesla, Amazon, Google, Microsoft - Banken, Krankenhäuser, Regierungen - Millionen von Websites Schaden: Milliarden Dollar weltweit Das war EINE Library. EINE Zeile Code in log4j. Weltweit Chaos.
Wie hilft dir OWASP bei sowas?
Timeline Log4Shell:
24. Nov 2021: Security-Forscher findet Bug
9. Dez 2021: CVE-2021-44228 wird öffentlich
└─ Ab jetzt ist es in der NVD-Datenbank!
└─ Ab jetzt findet OWASP es!
10. Dez 2021: Du führst OWASP-Scan aus
└─ OWASP lädt neue NVD-Daten
└─ Findet log4j 2.14.0 in deinem Projekt
└─ Matched gegen CVE-2021-44228
└─ BUILD FAILED! 🔴
└─ Du weißt: "Ich bin betroffen!"
Ohne OWASP:
❌ Du weißt nicht ob du betroffen bist
❌ Du weißt nicht welche Version du hast
❌ Du weißt nicht ob es transitiv reinkam
❌ Du hörst erst davon wenn Production gehackt wird
Mit OWASP:
✅ Automatischer Scan findet es sofort
✅ Du siehst: log4j 2.14.0 ist drin
✅ Du siehst: CVE-2021-44228 betrifft dich
✅ Du siehst: Version 2.17.1+ ist sicher
✅ Fix BEVOR Production betroffen ist
OWASP entdeckt keine NEUEN Bugs – das machen Security-Forscher.
OWASP zeigt dir ob BEKANNTE Bugs in DEINEM Projekt sind – das ist der Unterschied!
Das ist wie: Jemand der für dich in Security-Berichten nachschaut, ob eine deiner Libraries in der Vergangenheit als unsicher gemeldet wurde.
Genauer gesagt:
- ❌ KEIN Virenscanner (der findet NEUE Viren)
- ✅ Eher wie: Eine Rückrufliste für defekte Autoteile
- Auto-Hersteller findet defekte Bremsen
- Veröffentlicht Rückruf-Nummer
- Du gibst deine Fahrgestellnummer ein
- System sagt: „Ja, dein Auto ist betroffen!“
Stefan’s Log4Shell-Story:
„Am 10. Dezember 2021, 11 Uhr morgens, kam die erste Meldung zu Log4Shell. Panik im Team. Ich hab sofort OWASP über alle unsere Projekte laufen lassen. Ergebnis: 12 von 15 Projekten hatten log4j drin. Die meisten wussten wir nicht mal! 3 davon waren in Production. Bis 18 Uhr hatten wir alle gepatcht. Ohne OWASP hätten wir Tage gebraucht um rauszufinden WO überall log4j drin ist.“
Was sind transitive Dependencies? (Das versteckte Problem)
# Du schreibst in pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
# Maven lädt heimlich (transitive Dependencies):
spring-boot-starter-web
└─ spring-web
└─ spring-core
└─ commons-logging
└─ log4j-api
└─ log4j-core 2.14.0 ← DA IST ER! Mit Log4Shell!
Du hast log4j NIE in deine pom.xml geschrieben!
Aber es ist trotzdem da!
Als "Dependency einer Dependency einer Dependency"
Und es hat die kritischste Sicherheitslücke der letzten 10 Jahre!
Warum werden Dependencies nicht aktualisiert?
Typische Gründe (alle falsch!): ❌ "Läuft doch, warum ändern?" → Läuft unsicher! ❌ "Angst dass was kaputt geht" → Lieber Production gehackt als Tests rot? ❌ "Haben wir nie gemacht" → Deshalb gibt's Log4Shell-Incidents ❌ "Zu viel Arbeit" → Eine Zeile in pom.xml ändern vs. Incident-Report schreiben?
OWASP findet das alles. Automatisch. Bevor es Production erreicht.
Der CVSS-Score erklärt:
CVSS = Common Vulnerability Scoring System (0-10 Punkte) 9.0-10.0 = 🔴 CRITICAL "Sofort fixen! Production-Killer!" Beispiel: Log4Shell, Heartbleed 7.0-8.9 = 🟠 HIGH "Diese Woche fixen!" Beispiel: Remote Code Execution möglich 4.0-6.9 = 🟡 MEDIUM "Bald fixen, aber nicht heute" Beispiel: Information Disclosure 0.1-3.9 = 🟢 LOW "Nice to fix, irgendwann" Beispiel: Minor Information Leak 0.0 = Keine Sicherheitslücke
Wir setzen die Grenze bei 7.0 – das ist Industry-Standard für „ernsthaftes Risiko“.
💻 GitHub Actions: OWASP Integration
Schritt für Schritt – alles erklärt:
# .github/workflows/security-gate.yml
name: Security Gate
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
owasp-check:
runs-on: ubuntu-latest
steps:
# SCHRITT 1: Code holen
# GitHub Actions startet mit leerem Container
# Wir brauchen unseren Code für den Scan
- name: Checkout code
uses: actions/checkout@v4
# SCHRITT 2: Java installieren
# Maven (für OWASP) braucht Java
# 'cache: maven' spart Zeit bei Dependencies
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: 'maven' # ← Cached Dependencies = schnellerer Build!
# SCHRITT 3: OWASP Dependency Check ausführen
# Das ist der Kern des Security-Scans
- name: Run OWASP Dependency Check
run: |
mvn org.owasp:dependency-check-maven:check \
-DfailBuildOnCVSS=7 \
-DsuppressionFile=owasp-suppressions.xml
# Was passiert hier genau?
# 1. Maven lädt das OWASP-Plugin
# 2. Plugin lädt die NVD-Datenbank (~500 MB, beim ersten Mal)
# 3. Plugin analysiert deine pom.xml
# 4. Findet ALLE Dependencies (direkt + transitiv)
# 5. Vergleicht jede Library gegen NVD
# 6. Findet Matches = Vulnerabilities!
# 7. Berechnet CVSS-Score für jeden Fund
# 8. Bei CVSS >= 7 → Build schlägt fehl
# Parameter erklärt:
# -DfailBuildOnCVSS=7
# → Build fails bei Critical/High (>= 7.0)
# → Medium/Low Findings = nur Warnings
#
# -DsuppressionFile=owasp-suppressions.xml
# → Datei für bekannte False Positives
# → Manchmal meldet OWASP Dinge die bei DIR OK sind
# → Diese kannst du dokumentiert ausschließen
# SCHRITT 4: Report hochladen
# Wichtig: "if: always()" = auch bei Failure!
# So kannst du sehen WAS schiefgelaufen ist
- name: Upload OWASP Report
if: always()
uses: actions/upload-artifact@v3
with:
name: owasp-security-report
path: target/dependency-check-report.html
# Der Report ist eine HTML-Datei mit:
# - Liste aller gefundenen CVEs
# - CVSS-Score für jeden Fund
# - Betroffene Library + Version
# - Empfohlene sichere Version
# - Links zu CVE-Details
Was siehst du nach dem Push?
GitHub → Dein Repo → Actions Tab Security Gate (2m 15s) ├─ Checkout code ✅ (5 Sekunden) ├─ Set up JDK 21 ✅ (10 Sekunden, gecacht) ├─ Run OWASP Dependency Check ❌ FAILED (2 Minuten) │ │ Output: │ [INFO] Checking for updates │ [INFO] Download NVD database (first run) │ [INFO] Analyzing dependencies... │ [ERROR] │ │ Found 3 vulnerabilities with CVSS >= 7.0: │ │ 1. CVE-2021-44228 (Log4Shell) │ Library: log4j-core 2.14.0 │ CVSS: 10.0 🔴 CRITICAL │ Fix: Upgrade to 2.17.1+ │ │ 2. CVE-2023-12345 │ Library: jackson-databind 2.13.0 │ CVSS: 8.1 🔴 HIGH │ Fix: Upgrade to 2.15.0+ │ │ 3. CVE-2022-67890 │ Library: spring-web 5.3.10 │ CVSS: 7.5 🔴 HIGH │ Fix: Upgrade to 6.0.0+ │ │ [ERROR] Build failed due to critical vulnerabilities │ └─ Upload OWASP Report ✅ (Artifact verfügbar zum Download) BUILD FAILED ❌
Was machst du jetzt?
1. Report runterladen:
GitHub Actions → Dein fehlgeschlagener Build → Artifacts → Download "owasp-security-report" → Öffne .html-Datei im Browser
2. Report analysieren: Der HTML-Report zeigt dir:
- Detaillierte Beschreibung jedes CVE
- Welche deiner Dependencies betroffen ist
- Welche Version sicher ist
- Links zur CVE-Datenbank für mehr Infos
3. Dependencies fixen:
<!-- pom.xml - VORHER (unsicher) -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.0</version> <!-- 🔴 CVE-2021-44228 -->
</dependency>
<!-- pom.xml - NACHHER (sicher) -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version> <!-- ✅ Gefixt! -->
</dependency>
4. Erneut pushen:
git add pom.xml git commit -m "fix: Update log4j to fix CVE-2021-44228" git push origin main # Pipeline läuft wieder # Diesmal: Alle Checks ✅ GRÜN!
🏢 Jenkins: OWASP Integration
Warum sieht Jenkins anders aus?
Jenkins nutzt Groovy (Programmiersprache) für Pipelines.
GitHub Actions nutzt YAML (Konfiguration).
Gleiche Funktionalität, andere Syntax.
Jenkins-Konzepte:
stage()= Logischer Blocksteps{}= Was im Block passiertparallel{}= Mehrere Dinge gleichzeitigpost{}= Was nach dem Block passiert
// Jenkinsfile - Security Stage
stage('Security Gate') {
steps {
script {
// Maven-Befehl - identisch zu GitHub Actions!
sh '''
mvn org.owasp:dependency-check-maven:check \
-DfailBuildOnCVSS=7 \
-DsuppressionFile=owasp-suppressions.xml
'''
// Was passiert:
// 1. Jenkins führt Shell-Befehl aus
// 2. Maven startet OWASP-Plugin
// 3. Plugin lädt NVD (beim ersten Mal ~5 Min)
// 4. Plugin scannt alle Dependencies
// 5. Bei CVSS >= 7 → Exit-Code 1 → Build fails
}
}
// post = Was NACH diesem Stage passiert
post {
// always = IMMER ausführen (auch bei Failure)
always {
// HTML-Report in Jenkins UI verfügbar machen
publishHTML([
reportDir: 'target', // Wo liegt der Report?
reportFiles: 'dependency-check-report.html',
reportName: 'OWASP Security Report',
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true
])
// Jetzt kannst du in Jenkins auf
// "OWASP Security Report" klicken
// und den Report direkt sehen!
}
failure {
// Bei Failure: Team benachrichtigen
mail to: 'security@java-fleet.com',
subject: "🚨 Security Vulnerabilities found in ${env.JOB_NAME}",
body: """
Build ${env.BUILD_NUMBER} hat kritische Sicherheitslücken gefunden.
Report: ${env.BUILD_URL}OWASP_Security_Report
Bitte umgehend prüfen und fixen!
"""
}
}
}
Was siehst du in Jenkins?
Jenkins Dashboard → Dein Job → Build #142 Security Gate (2m 30s) ❌ FAILED │ ├─ Console Output: │ [INFO] Scanning dependencies... │ [ERROR] Found 3 vulnerabilities with CVSS >= 7.0 │ [ERROR] CVE-2021-44228 (CVSS: 10.0) in log4j-core 2.14.0 │ [ERROR] Build failed │ ├─ Reports: │ └─ [OWASP Security Report] ← Klickbar! │ └─ Build Status: FAILURE 📧 Mail sent to security@java-fleet.com
Du klickst auf „OWASP Security Report“:
- Öffnet HTML im Jenkins-Browser
- Zeigt alle Details zu den CVEs
- Mit Links zu Fixes
🐳 Teil 2: Trivy Container Scanning
Was ist Trivy?
Ein Tool von Aqua Security, das Container-Images auf Sicherheitslücken scannt.
Was scannt Trivy?
Dein Docker-Image
│
├─ OS-Packages
│ ├─ Ubuntu 22.04 Base Image
│ ├─ apt packages (curl, openssl, etc.)
│ └─ System Libraries (libc, libssl, etc.)
│
├─ Application-Dependencies
│ ├─ Java Runtime (JRE)
│ ├─ Deine JAR-Files
│ └─ Embedded Libraries (Tomcat, etc.)
│
└─ Secrets (Bonus!)
├─ API-Keys im Code?
├─ Passwords in ENV-Vars?
└─ Private Keys committed?
Warum zusätzlich zu OWASP?
# Deine pom.xml ist sauber ✅
# OWASP findet nichts ✅
# Aber dein Dockerfile:
FROM ubuntu:18.04 ← 2018! Mit 247 CVEs! ❌
RUN apt-get install -y \
curl \ ← Alte Version mit 12 CVEs
openssl \ ← Alte Version mit 8 CVEs
libssl1.0.0 ← Deprecated, 15 CVEs
# Trivy findet DAS!
# OWASP würde es nicht finden (nicht in pom.xml)
💻 GitHub Actions: Trivy Integration
# .github/workflows/security-gate.yml (erweitert)
name: Security Gate
on:
push:
branches: [ main, develop ]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: 'maven'
# OWASP für Java-Dependencies
- name: OWASP Dependency Check
run: |
mvn org.owasp:dependency-check-maven:check \
-DfailBuildOnCVSS=7
- name: Upload OWASP Report
if: always()
uses: actions/upload-artifact@v3
with:
name: owasp-report
path: target/dependency-check-report.html
# Docker-Image bauen
- name: Build Docker Image
run: docker build -t persons-api:${{ github.sha }} .
# Was ist ${{ github.sha }}?
# → Git-Commit-Hash (z.B. "a3f4b2c1d5e...")
# → Jedes Image bekommt eindeutigen Tag
# → Später nachvollziehbar: Welches Image = welcher Code?
# Trivy für Container-Security
- name: Run Trivy Security Scan
uses: aquasecurity/trivy-action@master
with:
image-ref: persons-api:${{ github.sha }}
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
exit-code: '1'
# Parameter erklärt:
# image-ref: Welches Image scannen?
# format: 'sarif' = Security-Standard-Format
# output: Wo Report speichern?
# severity: 'CRITICAL,HIGH' = Nur ernste Probleme
# exit-code: '1' = Bei Fund → Build fails
# Was scannt Trivy?
# 1. Lädt Vulnerability-Datenbanken
# 2. Analysiert alle Layers im Docker-Image
# 3. Findet installierte OS-Packages
# 4. Findet Application-Dependencies
# 5. Vergleicht gegen 50+ Vulnerability-DBs
# 6. Findet Secrets (API-Keys, Passwords)
# 7. Generiert SARIF-Report
# 8. Bei Critical/High → Exit 1 → Build fails
# Trivy-Ergebnisse zu GitHub Security senden
- name: Upload Trivy to GitHub Security
uses: github/codeql-action/upload-sarif@v2
if: always()
with:
sarif_file: 'trivy-results.sarif'
# Warum das cool ist:
# → GitHub Security Tab zeigt alle Findings
# → Automatische Alerts bei neuen CVEs
# → Dependabot kann Auto-Fix-PRs erstellen
# → Security-Team hat Überblick
Was siehst du nach dem Scan?
GitHub Actions → Security Gate Security Gate (3m 45s) ├─ OWASP Check ✅ (2 Min) ├─ Build Docker Image ✅ (1 Min) └─ Trivy Scan ❌ FAILED (45 Sek) Trivy Output: ┌─────────────────────────────────────────────┐ │ Target: persons-api:a3f4b2c │ ├─────────────────────────────────────────────┤ │ Total: 23 vulnerabilities (12 HIGH, 11 CRITICAL) │ │ HIGH Vulnerabilities: │ ├─ CVE-2023-12345 in curl 7.68.0 │ ├─ CVE-2023-67890 in openssl 1.1.1f │ └─ ... (10 more) │ │ CRITICAL Vulnerabilities: │ ├─ CVE-2024-99999 in libc6 2.31 │ ├─ CVE-2024-88888 in libssl1.1 │ └─ ... (9 more) └─────────────────────────────────────────────┘ BUILD FAILED ❌
Du gehst zu GitHub Security Tab:
GitHub → Dein Repo → Security → Code scanning alerts Du siehst: - 12 HIGH severity alerts - 11 CRITICAL severity alerts - Sortiert nach Severity - Mit Fix-Vorschlägen
Wie fixst du Container-Vulnerabilities?
Option 1: Neueres Base-Image:
# Dockerfile - VORHER FROM ubuntu:20.04 ← 2020, viele CVEs # Dockerfile - NACHHER FROM ubuntu:22.04 ← 2022, weniger CVEs
Option 2: Distroless Image (am besten!):
# Dockerfile - VORHER FROM ubuntu:22.04 RUN apt-get update && apt-get install -y openjdk-21-jdk COPY target/*.jar app.jar ENTRYPOINT ["java", "-jar", "/app.jar"] # Problem: # - Ubuntu Base = ~100 MB + viele Packages # - apt, curl, bash, etc. → Attack Surface! # - Viele Dependencies → viele CVEs # Dockerfile - NACHHER (BEST PRACTICE!) FROM gcr.io/distroless/java21-debian12 COPY target/*.jar /app.jar ENTRYPOINT ["java", "-jar", "/app.jar"] # Vorteile: # - Nur Java + deine App # - Keine Shell, keine apt, keine OS-Tools # - ~50 MB statt ~200 MB # - Minimale Attack Surface # - Fast keine CVEs!
🏢 Jenkins: Trivy Integration
// Jenkinsfile - Mit Trivy
stage('Security Gate') {
// parallel = Beide Scans gleichzeitig
parallel {
stage('OWASP Check') {
steps {
sh '''
mvn org.owasp:dependency-check-maven:check \
-DfailBuildOnCVSS=7
'''
}
post {
always {
publishHTML([
reportDir: 'target',
reportFiles: 'dependency-check-report.html',
reportName: 'OWASP Report'
])
}
}
}
stage('Trivy Container Scan') {
steps {
script {
// Image mit Build-Nummer taggen
def imageTag = "${env.BUILD_NUMBER}"
// Docker-Image bauen
sh "docker build -t persons-api:${imageTag} ."
// Trivy-Scan ausführen
sh """
trivy image \
--severity CRITICAL,HIGH \
--exit-code 1 \
--format json \
--output trivy-report.json \
persons-api:${imageTag}
"""
// Was macht Trivy?
// 1. Scannt Docker-Image
// 2. Findet OS + App Vulnerabilities
// 3. Nur CRITICAL + HIGH
// 4. Speichert als JSON
// 5. Exit-Code 1 bei Fund → Build fails
}
}
post {
always {
// Report als Jenkins Artifact speichern
archiveArtifacts artifacts: 'trivy-report.json'
// Optional: JSON zu HTML konvertieren
sh '''
trivy image \
--format template \
--template "@contrib/html.tpl" \
--output trivy-report.html \
persons-api:${BUILD_NUMBER}
'''
publishHTML([
reportDir: '.',
reportFiles: 'trivy-report.html',
reportName: 'Trivy Security Report'
])
}
}
}
}
}
✅ Checkpoint: Hast du Teil 2 gemeistert?
Kontrolliere:
- [ ] OWASP in GitHub Actions integriert
- [ ] OWASP in Jenkins integriert (falls du Jenkins nutzt)
- [ ] Trivy in GitHub Actions integriert
- [ ] Trivy in Jenkins integriert (falls du Jenkins nutzt)
- [ ] Einen Security-Scan durchgeführt (auch wenn alles grün ist)
- [ ] Weißt wie du OWASP-Reports liest
- [ ] Weißt wie du Trivy-Findings fixst
- [ ] Verstehst warum 80% der Vulnerabilities aus Dependencies kommen
Alles ✅? Du bist bereit für Teil 3 – Coverage Gates!
Nicht alles geschafft?
- OWASP-Setup dauert beim ersten Mal länger (NVD-Download)
- Trivy braucht Docker – wenn du nur Jenkins hast, skip den Teil
- Du kannst mit OWASP starten und Trivy später hinzufügen
Bonus-Punkte:
- [ ] False Positive in owasp-suppressions.xml dokumentiert
- [ ] Distroless Docker-Image ausprobiert
- [ ] GitHub Security Tab aktiviert
- [ ] OWASP lokal vor dem Commit ausgeführt
❓ FAQ – Security Gates Edition
Frage 1: OWASP-Check dauert beim ersten Mal 10 Minuten – normal?
Antwort: Ja! Beim ersten Mal lädt OWASP die komplette NVD-Datenbank (~500 MB). Danach nur noch Updates (30-60 Sekunden). In GitHub Actions wird die DB nicht gecacht zwischen Builds, daher immer 2-3 Minuten.
Frage 2: Trivy findet 50+ Vulnerabilities – muss ich alle fixen?
Antwort: Nein! Wir scannen nur auf CRITICAL + HIGH. Die musst du fixen. MEDIUM/LOW kannst du priorisieren. Tipp: Wechsel zu distroless Image → 90% der Findings verschwinden!
Frage 3: False Positive – wie suppresse ich das?
Antwort: Erstelle owasp-suppressions.xml:
<?xml version="1.0" encoding="UTF-8"?>
<suppressions>
<suppress>
<notes>False positive - not affected version</notes>
<cve>CVE-2024-12345</cve>
</suppress>
</suppressions>
ABER: Dokumentiere WARUM es ein False Positive ist!
Frage 4: Kann ich Security-Scans überspringen für Hotfixes?
Antwort: NEIN! 😱 Gerade bei Hotfixes unter Zeitdruck passieren die meisten Fehler. Security ist nicht optional. Wenn’s brennt: Fix in separatem Branch, Security-Check, dann Merge + Deploy.
Frage 5: OWASP vs. Trivy vs. Snyk vs. …?
Antwort:
- OWASP: Free, Open Source, Java-focused
- Trivy: Free, Open Source, Container-focused
- Snyk: Commercial, sehr gut, aber kostet
- Dependabot: GitHub-native, automatische PRs
Für den Start: OWASP + Trivy reichen völlig!
Frage 6: Wie oft sollte ich scannen?
Antwort: Bei jedem Push! Neue CVEs werden täglich gefunden. Ein heute sicheres Image kann morgen unsicher sein. Deshalb Security Gates in der Pipeline – automatisch bei jedem Build!
Frage 7: Was macht ihr bei persönlichen Problemen zwischen den Projekten?
Antwort: Das ist… kompliziert. Manche Geschichten gehören nicht in Tech-Blogs, sondern in private logs. Aber das ist ein anderes Kapitel unserer Geschichte. 🔒
📚 Die CI/CD-Serie im Überblick
✅ Bereits erschienen:
- Teil 1 (24.10.2025): Von Manual zu Pipeline – Erste Automation
👉 Du bist hier:
- Teil 2 (31.10.2025): Security Gates – OWASP & Trivy
🔒 Demnächst:
- Teil 3 : Coverage Gates – JaCoCo & Test-Qualität
- Teil 4 : Quality Gates – SonarQube & Technical Debt
- Teil 5 : Docker Multi-Stage Builds optimieren
- Teil 6 : Container Security – Trivy, Syft & SBOM
- Teil 7 : Registry Integration & Image-Tagging
- Teil 8: Deployment-Strategien, Kubernetes & Enterprise-Patterns
📥 Downloads & Ressourcen
Heute für dich:
- 📄 GitHub Actions Security Template
- 📄 Jenkins Security Pipeline
- 📄 OWASP Suppressions Template
- 📄 Distroless Dockerfile
- 📄 Security Gates Cheat-Sheet
Alle Templates getestet mit:
- ✅ Spring Boot 3.2+
- ✅ Maven 3.9
- ✅ Java 21
- ✅ Docker 24
🎓 Was du heute gelernt hast
Du kannst jetzt:
- ✅ Erklären warum 80% der Vulnerabilities aus Dependencies kommen
- ✅ OWASP Dependency Check in Pipelines einbauen
- ✅ Container mit Trivy scannen
- ✅ CVSS-Scores interpretieren
- ✅ Security-Reports lesen und Findings fixen
- ✅ False Positives dokumentiert suppressen
- ✅ Entscheiden wann distroless Images Sinn machen
- ✅ OWASP auch lokal nutzen (vor dem Commit!)
Code Sentinel’s Fazit:
„Security-Scans sind wie Rauchmelder – sie nerven beim Testen, aber sie retten dir den Arsch wenn’s brennt. Stefan’s Log4Shell-Incident? Hätte mit OWASP nie passieren dürfen. Jetzt hat er Security Gates in allen Projekten. Seit 3 Wochen kein Security-Incident mehr.“
Stefan fügt hinzu:
„Ich hab jetzt OWASP + Trivy in allen meinen Projekten. Mein Chef fragt nicht mehr ob ich Security mache – die Pipeline zeigt’s ihm. Grüner Build = sicherer Build. So einfach ist das.“
🔮 Nächste Woche: Coverage Gates
Teil 3 :
Coverage Gates – JaCoCo & Test-Qualität
Warum 100% Coverage eine Lüge ist
Anna aus München hat 147 Tests – alle grün! Aber als sie deployed hat, war Production sofort down. Das Problem? Die Tests haben zwar 95% Coverage, aber sie testen nichts Wichtiges.
Nächste Woche lernst du:
- JaCoCo für Line, Branch & Complexity Coverage
- Was Coverage wirklich misst (und was nicht)
- Test-Pyramide in der Pipeline
- Wie du sinnvolle von nutzlosen Tests unterscheidest
- Warum 147 grüne Tests Production trotzdem killen können
Lass uns zusammen rausfinden, ob deine Tests wirklich testen! 🧪
🎯 Community-Challenge: „Security Hero“
Die Challenge diese Woche:
- Baue Security Gates in deine Pipeline (OWASP + Trivy)
- Scanne dein Projekt (auch wenn du denkst es ist sicher)
- Finde mindestens 1 Vulnerability (jeder findet was!)
- Fixe das Problem
- Screenshot vom grünen Build NACH dem Fix
- Teile mit #JavaFleetSecurity
Die besten 3 Hero-Stories:
- 🏆 Feature im nächsten Blogpost
- 🎁 Security Cheat-Sheet (exclusive)
- ⭐ Personal Security-Review von Code Sentinel
Deadline: Nächsten Sonntag, 23:59 Uhr
💌 Bis nächste Woche!
Das war Teil 2 der CI/CD-Serie! Security Gates sind jetzt drin – kein Deployment mehr ohne Check!
Fun Fact: Unsere Website hat mehr als nur Tech-Content! Wer neugierig ist und mal die Suche oben auf java-developer.online ausprobiert… manchmal verstecken sich die interessantesten Geschichten zwischen den Code-Zeilen. Schmerz vom Herz ist nicht nur ein Tech-Problem, oder? 💔
Aber das nur als Tipp für die besonders Neugierigen unter euch!
Fragen? Findings? Security-Horrorstories?
Schreib mir:
- 📧 code.sentinel@java-fleet.com
- 💬 Twitter: @CodeSentinelDev
- 💼 LinkedIn: Code Sentinel
Und vergiss nicht: Teile deinen ersten Security-Fund mit #JavaFleetSecurity!
Wir sehen uns nächste Woche bei den Coverage Gates. 🛡️
— Code Sentinel
P.S. Stefan hat letzte Woche 3 CVEs gefunden. Diese Woche: 0. Security Gates funktionieren.
P.P.S. Kofi meint ich soll auch Grype zeigen. Vielleicht in Teil 12.
P.P.P.S. Lisa? Nächste Woche hat sie Geburtstag. Hab schon was überlegt…
🎬 Bernd’s Corner
„Security-Scans in der Pipeline.
Endlich. Wurde auch Zeit.
Ich hatte OWASP schon 2013 in der Pipeline. Damals hieß das noch Dependency-Check-CLI. Hat keiner verstanden.
Jetzt ist’s ‚modern‘ und ‚DevSecOps‘. Die Kids denken sie haben’s erfunden.
Und Trivy? Container-Scanning? Hatte ich auch schon. Mit Clair. 2016. Hat nur keiner ernst genommen.
Aber gut, macht’s halt jetzt. Besser spät als bei Log4Shell.
Und wer seine Dockerfile mit ubuntu:18.04 anfängt, dem ist sowieso nicht mehr zu helfen.
— Bernd, der schon Security hatte als ihr noch ‚curl | bash‘ gemacht habt“
📊 Nächster Post: Coverage Gates – Warum 100% Coverage eine Lüge ist
🔔 Newsletter: Hier anmelden für Early Access
Tags: #SecurityGates #OWASP #Trivy #ContainerSecurity #DependencyCheck #CICD #DevSecOps #CVE #JavaSecurity
Serie: CI/CD-Grundlagen | Modul 1: Foundations (Teil 2 von 4)

