Loading...

Container Hardening and Vulnerability Scanning of WebGoat Using Trivy and Dockle

By Mohammad Jaafar
Container Hardening and Vulnerability Scanning of WebGoat Using Trivy and Dockle
DevOpsSecurityCI/CD

Introduction

Imagine deploying a containerized application only to discover it contains 37 critical vulnerabilities—including remote code execution (RCE) and server-side request forgery (SSRF) flaws. This isn't a hypothetical scenario; it's exactly what I encountered when working with OWASP WebGoat, a deliberately vulnerable application designed for security training.

In modern DevOps practices, container security is critical to ensuring the integrity and safety of applications deployed at scale. While containers encapsulate dependencies and runtime environments, they can also package vulnerabilities and misconfigurations that create attack vectors for malicious actors.

This project demonstrates a practical approach to container hardening by taking a vulnerable application—OWASP WebGoat—and systematically securing it using industry-standard tools: Trivy for vulnerability scanning and Dockle for best practice validation. I also implemented an automated CI/CD pipeline using GitHub Actions to enforce security standards and prevent vulnerable containers from reaching production.

Key outcomes:

  • Reduced critical vulnerabilities from 37 to 0
  • Achieved 100% compliance with Docker security best practices
  • Automated security scanning in CI/CD pipeline
  • Created a repeatable DevSecOps workflow

Approach and Implementation

🛠️ Container Hardening Workflow

Hardening Workflow

2.1 Initial Vulnerability Scanning

I started by scanning the the original image (webgoat/webgoat) using Trivy and Dockle.

  • Trivy detected multiple high and critical vulnerabilities, primarily in the xstream library, which is intentionally vulnerable in WebGoat to demonstrate insecure deserialization.
  • Dockle flagged issues like the use of the latest tag and presence of setuid/setgid binaries.

Table 1: Original WebGoat Image Issues (Pre-Hardening)

ToolFinding TypeDescription
TrivyCritical Vulnerabilitiesxstream deserialization RCEs and SSRF, multiple CVEs flagged
DockleBest Practice ViolationUse of latest tag, presence of setuid/setgid binaries

Figure 1 - Screenshot of Trivy output for webgoat/webgoat

Figure 1 - Screenshot of Trivy output for webgoat/webgoat

Figure 2 - Screenshot of Dockle output for webgoat/webgoat

Figure 2 - Screenshot of Dockle output for webgoat/webgoat


2.2 Dockerfile Hardening

To mitigate risks and improve security, I created two hardened Dockerfiles:

  1. A Dockerfile that starts from the official WebGoat image, removing setuid/setgid binaries and adding a HEALTHCHECK instruction.
  2. A fully hardened Dockerfile from scratch using eclipse-temurin:24-jdk-alpine, which:
    • Creates a non-root user
    • Uses a writable, isolated work directory
    • Disables schema generation to avoid permission issues with Hibernate (-Dhibernate.hbm2ddl.auto=none)
    • Binds WebGoat to 0.0.0.0 using Dserver.address=0.0.0.0
  3. Avoided exposing sensitive config via environment variables by using an entrypoint.sh script

Table 2: Hardening Strategies Applied:

TechniqueDescription
Dropped setuid/setgidPrevents privilege escalation via system binaries
Non-root userIsolates WebGoat runtime with minimal privileges
HEALTHCHECKEnables container health monitoring
Environment HardeningRemoved risky ENV exposure in ENTRYPOINT via wrapper script
Hibernate auto DDL disabledPrevents schema export in read-only environments
Binding to 0.0.0.0Ensures WebGoat is accessible from Docker container port

Dockerfile.patched

FROM eclipse-temurin:24-jdk-alpine # Create app directory and user RUN adduser -D -h /home/webgoat webgoat && \ mkdir -p /webgoat-data && \ chown -R webgoat:webgoat /webgoat-data # Copy JAR and entrypoint COPY webgoat-hardened.jar /webgoat/webgoat.jar COPY entrypoint.sh /entrypoint.sh # Make entrypoint executable RUN chmod +x /entrypoint.sh # Set ENTRYPOINT without exposing flags in Dockerfile ENTRYPOINT ["/entrypoint.sh"] # Set working directory to writable one WORKDIR /webgoat-data USER webgoat # Expose app port EXPOSE 8080 # Add healthcheck for Docker HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \ CMD wget -q --spider http://localhost:8080/WebGoat || exit 1

entrypoint.sh:

#!/bin/sh exec java -Dserver.address=0.0.0.0 -Dhibernate.hbm2ddl.auto=none -jar /webgoat/webgoat.jar

CI/CD Pipeline (GitHub Actions)

CI/CD Pipeline

2.3 CI/CD Pipeline with GitHub Actions

I automated the container security process using a GitHub Actions CI/CD workflow. This workflow:

  • Triggers on push

  • Builds the hardened Docker image

  • Runs Trivy and Dockle scans

  • Stores the scan reports (trivy-report.json, dockle-report.json) in a reports/ directory

  • Uploads reports as GitHub Actions artifacts

  • Fails the build if any CRITICAL vulnerabilities are detected by Trivy

    Table 3: CI/CD Pipeline Overview:

StageTool/Action UsedDescription
TriggerGitHub ActionsRuns on push and pull request events
Build Imagedocker buildBuilds the hardened image from patched Dockerfile
Vulnerability ScanTrivyScans for CRITICAL and HIGH CVEs; fails build if found
Best Practice ScanDockleChecks Dockerfile security practices; fails build on FATAL/WARN issues
Artifact Uploadactions/upload-artifact@v4Uploads scan results (.json and .txt) for traceability
Security EnforcementExit codesEnsures only compliant images proceed through the pipeline

Figure 4 - GitHub Actions pipeline with Trivy and Dockle scan results as artifacts

Figure 4 - GitHub Actions pipeline with Trivy and Dockle scan results as artifacts


Results

3.1 Before vs. After Comparison

Vulnerability Scanning (Trivy)

  • Before Hardening: 37 vulnerabilities detected, many related to xstream
  • After Hardening: 0 high/critical vulnerabilities detected

Best Practices (Dockle)

  • Before: 1 warning (latest tag), 2 info messages (setuid/setgid)
  • After: All 16 checks passed

Table 4: Before vs. After Comparison Summary

Scan ToolMetricOriginal ImageHardened Image
TrivyCRITICAL Vulnerabilities30+ (mainly xstream)0
TrivyHIGH Vulnerabilities10+0
DockleWarnings1 (latest tag)0
DockleInformational Issues2 (setuid/setgid files)0

Before vs. After Vulnerability Comparison

Before vs After Comparison

Figure 5 - Clean Trivy Report Comparison between original image and hardened image

Figure 5 - Clean Trivy Report Comparison between original image and hardened image

Figure 6 - Clean Dockle Report Comparison between original image and hardened image

Figure 6 - Clean Dockle Report Comparison between original image and hardened image


Discussion

I found that binding the server to 0.0.0.0 was necessary for the container to expose the app correctly. Additionally, disabling Hibernate's schema auto-generation (hibernate.hbm2ddl.auto) resolved write-access errors in the container's read-only filesystem.

While the pipeline automates security scanning, the Trivy scan slowed significantly due to the large .jar size. Optimizing artifact size or excluding static files in scans could improve performance.

This exercise reinforced best practices in secure development and showed how automated pipelines can enforce policies consistently.


Conclusion

This project demonstrates that container security isn't just about scanning for vulnerabilities—it's about building a comprehensive security-first approach to container development and deployment. Starting from a deliberately vulnerable image, I successfully built a secure and hardened container that meets enterprise security standards.

Key Takeaways:

  1. Automation is Essential: Manual security checks don't scale. The CI/CD pipeline ensures every container build is automatically scanned and validated.

  2. Defense in Depth: Combining multiple tools (Trivy + Dockle) provides comprehensive coverage—vulnerability scanning plus best practice validation.

  3. Security by Design: Hardening containers from the start is more effective than trying to secure them after deployment.

  4. Measurable Results: The transformation from 37 critical vulnerabilities to zero demonstrates the effectiveness of systematic container hardening.

Next Steps for Your Organization:

  • Integrate Trivy and Dockle into your existing CI/CD pipelines
  • Establish security gates that prevent vulnerable containers from reaching production
  • Create hardened base images for your applications
  • Implement regular security scanning of your container registry

This project highlights the importance of integrating security early in the development pipeline and shows how container security can be embedded directly into development practices, creating a true DevSecOps culture.


References