Skip to content

sbmaggarwal/java-semgrep-demo

Repository files navigation

Java Semgrep Security Demo

Overview

This project demonstrates how to use Semgrep, a static application security testing (SAST) tool, to detect and fix common security vulnerabilities in Java applications. The repository contains two branches showcasing vulnerable and secure implementations of the same functionality.

Project Structure

java-semgrep-demo/
├── src/main/java/com/example/demo/
│   ├── VulnerableApp.java (vulnerable branch)
│   └── SecureApp.java (fixed branch)
├── .semgrep.yml (Custom Semgrep rules)
├── build.gradle (Gradle build configuration)
├── run-semgrep.sh (Automated scanning script)
└── README.md (This file)

Branches

1. vulnerable Branch

Contains intentionally vulnerable code with common security issues:

  • CWE-798: Hardcoded credentials
  • CWE-89: SQL Injection
  • CWE-78: Command Injection
  • CWE-22: Path Traversal
  • CWE-327: Use of weak cryptographic algorithms (MD5, DES)
  • CWE-330: Use of insufficiently random values

2. fixed Branch

Contains the remediated version with security best practices:

  • Environment variables for credentials
  • Prepared statements for SQL queries
  • Input validation and sanitization
  • Path normalization and validation
  • Strong cryptography (SHA-256, AES-256)
  • SecureRandom for cryptographic operations

Security Vulnerabilities Demonstrated

1. Hardcoded Credentials (CWE-798)

Vulnerable:

private static final String DB_PASSWORD = "password123";
private static final String SECRET_KEY = "MySecretKey12345";

Secure:

private static final String DB_PASSWORD = System.getenv("DB_PASSWORD");
private static final String SECRET_KEY = System.getenv("SECRET_KEY");

2. SQL Injection (CWE-89)

Vulnerable:

String query = "SELECT * FROM users WHERE username = '" + username + 
              "' AND password = '" + password + "'";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);

Secure:

String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = conn.prepareStatement(query);
pstmt.setString(1, username);
pstmt.setString(2, hashPassword(password));
ResultSet rs = pstmt.executeQuery();

3. Command Injection (CWE-78)

Vulnerable:

String command = "echo " + userInput;
Process process = Runtime.getRuntime().exec(command);

Secure:

// Avoid shell execution entirely
String sanitized = userInput.replaceAll("[^a-zA-Z0-9\\s]", "");
System.out.println("Message: " + sanitized);

4. Path Traversal (CWE-22)

Vulnerable:

File file = new File("data/" + filename);
BufferedReader reader = new BufferedReader(new FileReader(file));

Secure:

Path basePath = Paths.get("data").toAbsolutePath().normalize();
Path filePath = basePath.resolve(filename).normalize();

if (!filePath.startsWith(basePath)) {
    System.out.println("Access denied: Invalid file path");
    return;
}

5. Weak Cryptography (CWE-327)

Vulnerable:

MessageDigest md = MessageDigest.getInstance("MD5");
Cipher cipher = Cipher.getInstance("DES");

Secure:

MessageDigest md = MessageDigest.getInstance("SHA-256");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

6. Weak Random Number Generation (CWE-330)

Vulnerable:

private static Random random = new Random();

Secure:

private static SecureRandom secureRandom = new SecureRandom();

Installation

Prerequisites

  • Java 11 or higher
  • Gradle
  • Git
  • macOS/Linux (for shell script) or Windows with Git Bash

Install Semgrep

macOS (Homebrew)

brew install semgrep

Linux/Windows/Other

pip install semgrep

Or using the official installer:

python3 -m pip install semgrep

Usage

1. Clone the Repository

git clone <repository-url>
cd java-semgrep-demo

2. Run Automated Security Scan

Execute the provided script to scan both branches:

./run-semgrep.sh

This script will:

  1. Switch to the vulnerable branch and run Semgrep
  2. Switch to the fixed branch and run Semgrep
  3. Display the results showing vulnerabilities found vs fixed

3. Manual Semgrep Commands

Scan with custom rules

# Switch to vulnerable branch
git checkout vulnerable
semgrep --config=.semgrep.yml src/

# Switch to fixed branch
git checkout fixed
semgrep --config=.semgrep.yml src/

Scan with Semgrep's auto rules

semgrep --config=auto src/

Scan for specific severity levels

semgrep --config=.semgrep.yml --severity ERROR src/

4. Build and Run the Application

Build the project

./gradlew build

Run the application

# On vulnerable branch
git checkout vulnerable
./gradlew run

# On fixed branch
git checkout fixed
./gradlew run

Semgrep Configuration

The .semgrep.yml file contains custom rules for detecting:

  • Hardcoded credentials
  • SQL injection vulnerabilities
  • Command injection vulnerabilities
  • Path traversal vulnerabilities
  • Weak cryptographic algorithms
  • Insecure random number generation

Each rule includes:

  • Pattern matching for vulnerable code
  • Severity levels (ERROR/WARNING)
  • CWE and OWASP references
  • Helpful remediation messages

Expected Results

Vulnerable Branch Scan Results

When scanning the vulnerable branch, Semgrep should detect:

  • 3 hardcoded credentials (DB_USERNAME, DB_PASSWORD, SECRET_KEY)
  • 1 SQL injection vulnerability
  • 1 command injection vulnerability
  • 1 path traversal vulnerability
  • 1 MD5 usage warning
  • 1 DES encryption error
  • 1 weak random number generator warning

Fixed Branch Scan Results

When scanning the fixed branch, Semgrep should find:

  • No vulnerabilities (all issues remediated)

Learning Objectives

This demo helps you understand:

  1. Common Security Vulnerabilities: How they appear in code and their potential impact
  2. Secure Coding Practices: Proper techniques to prevent security issues
  3. Static Analysis Tools: How Semgrep can automatically detect vulnerabilities
  4. DevSecOps Integration: How to incorporate security scanning into development workflow
  5. OWASP Top 10: Real examples of top security risks

Best Practices Demonstrated

  1. Never hardcode credentials - Use environment variables or secure vaults
  2. Always use parameterized queries - Prevent SQL injection
  3. Validate and sanitize input - Prevent injection attacks
  4. Normalize and validate file paths - Prevent directory traversal
  5. Use strong cryptography - SHA-256+ for hashing, AES for encryption
  6. Use SecureRandom - For cryptographically secure random values
  7. Implement defense in depth - Multiple layers of security controls

Integration with CI/CD

You can integrate Semgrep into your CI/CD pipeline:

GitHub Actions Example

name: Semgrep Security Scan
on: [push, pull_request]

jobs:
  semgrep:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: returntocorp/semgrep-action@v1
        with:
          config: .semgrep.yml

GitLab CI Example

semgrep:
  image: returntocorp/semgrep
  script:
    - semgrep --config=.semgrep.yml src/
  only:
    - merge_requests
    - main

Additional Resources

Contributing

This is a demonstration project for educational purposes. Feel free to:

  • Add more vulnerability examples
  • Improve the Semgrep rules
  • Enhance the secure implementations
  • Add unit tests

License

This project is for educational purposes. Use at your own risk.

Disclaimer

The vulnerable code in this repository is intentionally insecure for demonstration purposes. Never use the vulnerable patterns in production code.

About

The demo clearly shows how Semgrep can automatically detect security vulnerabilities and verify that fixes have been properly implemented.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors