DEV Community

Rahul Joshi
Rahul Joshi

Posted on

Why Great Code Still Gets Hacked: A Guide to SAST, DAST, and SCA

Introduction: The Security Paradox

You've written clean code. Your functions are elegant. Your architecture is solid. Yet, your application still has vulnerabilities. Why?

The truth is: Writing good code isn't enough. Modern applications have three attack surfaces that many developers overlook:

  1. Your own code (logic flaws, injection vulnerabilities)
  2. Your running application (configuration issues, authentication bypasses)
  3. Your dependencies (vulnerable third-party libraries)

This is where SAST, DAST, and SCA come in. Think of them as your security trinity—each guarding a different frontier.


The Security Testing Trinity

🔍 SAST (Static Application Security Testing)

What it does: Analyzes your source code without executing it

Tools: SonarQube, Semgrep

Analogy: A code review expert who reads every line looking for security issues

🎯 DAST (Dynamic Application Security Testing)

What it does: Tests your running application like a hacker would

Tools: OWASP ZAP, Nuclei

Analogy: An ethical hacker who attacks your live application to find weaknesses

📦 SCA (Software Composition Analysis)

What it does: Scans your dependencies for known vulnerabilities

Tools: OWASP Dependency Check, Snyk

Analogy: A supply chain inspector checking if any of your imported components are defective


Part 1: SAST with SonarQube

Why Your Code Needs Static Analysis

Even experienced developers write vulnerable code. Here's why:

// This looks innocent, but it's vulnerable to SQL injection
public User getUser(String username) {
    String query = "SELECT * FROM users WHERE username = '" + username + "'";
    return database.execute(query);
}
Enter fullscreen mode Exit fullscreen mode

A static analyzer catches this immediately and suggests a fix.

Setting Up SonarQube: Step-by-Step

Step 1: Install SonarQube Using Docker

# Pull and run SonarQube
docker run -d --name sonarqube \
  -p 9000:9000 \
  -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true \
  sonarqube:latest

# Wait for SonarQube to start (check logs)
docker logs -f sonarqube
Enter fullscreen mode Exit fullscreen mode

Access: Navigate to http://localhost:9000

Default credentials: admin/admin (change immediately!)

![SonarQube Docker container setup in progress]

Step 2: Create Your First Project

Once SonarQube is running, you'll see the project creation interface:

  1. Click "Create Project" → "Manually"
  2. Set a project key (e.g., my-secure-app)
  3. Generate a token for authentication
  4. Choose your build system (Maven, Gradle, npm, etc.)

Step 3: Scan a Java Project

# For Maven projects
mvn clean verify sonar:sonar \
  -Dsonar.projectKey=my-secure-app \
  -Dsonar.host.url=http://localhost:9000 \
  -Dsonar.login=your-token-here

# For Gradle projects
./gradlew sonar \
  -Dsonar.projectKey=my-secure-app \
  -Dsonar.host.url=http://localhost:9000 \
  -Dsonar.login=your-token-here
Enter fullscreen mode Exit fullscreen mode

Step 4: Analyze the Results

SonarQube categorizes issues by severity:

  • Blocker: SQL Injection, Command Injection (Fix immediately!)
  • Critical: XSS vulnerabilities, Hard-coded credentials
  • Major: Weak cryptography, Insecure randomness
  • Minor: Code smells that could lead to vulnerabilities

Real-World Example: Fixing a Vulnerability

SonarQube finding: "SQL Injection vulnerability detected"

// ❌ Vulnerable code
public void deleteUser(String userId) {
    String sql = "DELETE FROM users WHERE id = " + userId;
    jdbcTemplate.execute(sql);
}

// ✅ Fixed code
public void deleteUser(String userId) {
    String sql = "DELETE FROM users WHERE id = ?";
    jdbcTemplate.update(sql, userId);
}
Enter fullscreen mode Exit fullscreen mode

Pro Tips for SonarQube

  • Integrate with CI/CD: Fail builds if security issues exceed a threshold
  • Use Quality Gates: Define minimum security standards
  • Enable Security Hotspots: Review areas that need manual validation
  • Set up branch analysis: Scan feature branches before merging
# Example: GitLab CI integration
sonarqube-check:
  image: maven:3.8-openjdk-11
  script:
    - mvn verify sonar:sonar -Dsonar.projectKey=$CI_PROJECT_NAME
  only:
    - merge_requests
    - main
Enter fullscreen mode Exit fullscreen mode

Part 2: DAST with OWASP ZAP

Why Running Apps Need Dynamic Testing

Static analysis can't catch everything. Consider these scenarios:

  • Configuration issues: Exposed admin panels, default passwords
  • Authentication bypasses: Session management flaws
  • Server misconfigurations: Missing security headers
  • Business logic flaws: Password reset vulnerabilities

DAST tests your application as an attacker would—from the outside.

Setting Up OWASP ZAP: Step-by-Step

Step 1: Set Up a Test Target

For demonstration purposes, we'll use OWASP Juice Shop (a deliberately vulnerable application):

# Run Juice Shop as our test target
docker run -d --name juiceshop -p 3000:3000 bkimminich/juice-shop
Enter fullscreen mode Exit fullscreen mode

Step 2: Install and Run OWASP ZAP

# Using Docker (recommended)
docker pull zaproxy/zap-stable

# Run ZAP in daemon mode (headless)
docker run -u zap -p 8080:8080 -i zaproxy/zap-stable \
  zap.sh -daemon -host 0.0.0.0 -port 8080 \
  -config api.addrs.addr.name=.* \
  -config api.addrs.addr.regex=true \
  -config api.key=your-api-key-here

# Or download the desktop version from https://www.zaproxy.org/download/
Enter fullscreen mode Exit fullscreen mode

Step 3: Run a Baseline Scan (Quickest Way to Start)

Create a scan script to automate the process:

#!/usr/bin/env bash
# Get local IP so Docker container can reach the target
TARGET_IP=$(hostname -I | awk '{print $1}')
TARGET_URL="http://$TARGET_IP:3000"

echo "Starting Security Scan on: $TARGET_URL"

# Create a folder for reports
mkdir -p zap-reports

# Run ZAP Baseline Scan
docker run --rm -v $(pwd)/zap-reports:/zap/wrk/:rw \
  ghcr.io/zaproxy/zaproxy:stable zap-baseline.py \
  -t $TARGET_URL \
  -r juice_shop_report.html

echo "Scan Complete. Report generated in zap-reports/juice_shop_report.html"
Enter fullscreen mode Exit fullscreen mode

Step 4: Understanding ZAP Scan Results

When you run the scan, you'll see output categorized as:

  • PASS: Checks that didn't find vulnerabilities (good!)
  • WARN-NEW: New warnings detected
  • FAIL-NEW: Critical failures that need immediate attention

Common findings include:

  • Deprecated Feature Policy Header Set [10063]
  • Timestamp Disclosure - Unix [10096]
  • Cross-Domain Misconfiguration [10098]
  • Modern Web Application [10109]
  • Dangerous JS Functions [10110]
  • Insufficient Site Isolation Against Spectre Vulnerability [90004]

Step 5: Advanced Scan with API (Automation)

For more control, use the ZAP API:

# Set your API key
ZAP_API_KEY="your-api-key-here"
TARGET="http://localhost:3000"

# Start a spider scan
curl "http://localhost:8080/JSON/spider/action/scan/?url=$TARGET&apikey=$ZAP_API_KEY"

# Wait for spider to complete (poll status)
while : ; do
  PROGRESS=$(curl -s "http://localhost:8080/JSON/spider/view/status/?apikey=$ZAP_API_KEY" | jq -r '.status')
  echo "Spider progress: $PROGRESS%"
  [ "$PROGRESS" = "100" ] && break
  sleep 5
done

# Start active scan
SCAN_ID=$(curl -s "http://localhost:8080/JSON/ascan/action/scan/?url=$TARGET&apikey=$ZAP_API_KEY" | jq -r '.scan')

# Wait for active scan to complete
while : ; do
  STATUS=$(curl -s "http://localhost:8080/JSON/ascan/view/status/?scanId=$SCAN_ID&apikey=$ZAP_API_KEY" | jq -r '.status')
  echo "Active scan progress: $STATUS%"
  [ "$STATUS" = "100" ] && break
  sleep 10
done

# Generate HTML report
curl "http://localhost:8080/OTHER/core/other/htmlreport/?apikey=$ZAP_API_KEY" > zap_report.html
Enter fullscreen mode Exit fullscreen mode

Pro Tips for OWASP ZAP

  • Use ZAP in CI/CD: Automate scans on every deployment before production
  • Configure scan policies: Disable checks that cause false positives
  • Set up proxy mode: Manually browse your app through ZAP to build a better sitemap
  • Use ZAP scripts: Extend functionality with custom scripts
  • Start with baseline scans: Quick feedback, then move to full active scans

Part 3: SCA with OWASP Dependency Check

Why Your Dependencies Are Your Weakest Link

Consider this: The average application has 200+ dependencies. Each one is a potential vulnerability.

Famous incidents:

  • Equifax breach (2017): Unpatched Apache Struts vulnerability
  • Log4Shell (2021): Log4j vulnerability affected millions of applications

You didn't write the vulnerable code, but you're still responsible for it.

Setting Up OWASP Dependency Check: Step-by-Step

Step 1: Install OWASP Dependency Check

# Download the latest release
wget https://github.com/jeremylong/DependencyCheck/releases/download/v9.0.9/dependency-check-9.0.9-release.zip

# Unzip
unzip dependency-check-9.0.9-release.zip

# Add to PATH (optional)
export PATH=$PATH:$(pwd)/dependency-check/bin
Enter fullscreen mode Exit fullscreen mode

Step 2: Get NVD API Key

The National Vulnerability Database (NVD) requires an API key for faster, reliable scanning.

  1. Go to https://nvd.nist.gov/developers/request-an-api-key
  2. Fill out the form with your email
  3. Check your email for the API key
  4. Store it securely

Why you need it: Without an API key, scans are rate-limited and take 10x longer.

Step 3: Run Your First Scan

# Basic scan
dependency-check.sh \
  --project "My Demo project" \
  --scan ./target \
  --out ./report \
  --format HTML \
  --format JSON \
  --format XML \
  --nvdApiKey 5b2b7320-exxf-4b1e-95xx-bdxxxxxxxxxx \
  --failOnCVSS 7 \
  --enableExperimental
Enter fullscreen mode Exit fullscreen mode

Key parameters explained:

  • --project: Name of your project (appears in reports)
  • --scan: Directory to scan (e.g., ./target, ./node_modules)
  • --out: Where to save reports
  • --format: Output format (HTML for viewing, JSON for CI/CD)
  • --nvdApiKey: Your NVD API key (critical for performance)
  • --failOnCVSS 7: Fail the build if vulnerabilities with CVSS score ≥ 7 are found
  • --enableExperimental: Enable experimental analyzers for better coverage

Step 4: Scan Different Project Types

For Java/Maven Projects:

dependency-check.sh \
  --project "My Java App" \
  --scan ./target \
  --format HTML \
  --nvdApiKey YOUR_NVD_API_KEY_HERE
Enter fullscreen mode Exit fullscreen mode

For Node.js Projects:

# Scan node_modules directory
dependency-check.sh \
  --project "My Node App" \
  --scan ./node_modules \
  --format HTML \
  --nvdApiKey YOUR_NVD_API_KEY_HERE

# Or use npm audit (built-in)
npm audit

# Generate detailed report
npm audit --json > npm-audit-report.json
Enter fullscreen mode Exit fullscreen mode

Step 5: Analyze the Report

The report shows vulnerabilities with:

  • CVE ID: Unique identifier (e.g., CVE-2023-12345)
  • CVSS Score: Severity (0-10, where 7+ is critical)
  • Description: What the vulnerability does
  • Recommendation: How to fix it

Example vulnerability:

CVE-2023-12345 | CVSS: 9.8 (Critical)
Component: jackson-databind 2.9.8
Description: Deserialization vulnerability allows remote code execution
Recommendation: Update to version 2.15.0 or higher
Enter fullscreen mode Exit fullscreen mode

Real-World Example: Fixing a Dependency Vulnerability

Finding: Log4j vulnerability (CVE-2021-44228)

<!-- ❌ Vulnerable dependency in pom.xml -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.14.1</version>
</dependency>

<!-- ✅ Fixed: Updated to patched version -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.1</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

For Node.js:

# Find vulnerable packages
npm audit

# Auto-fix (when possible)
npm audit fix

# Force update breaking changes if necessary
npm audit fix --force

# Or update specific package
npm update log4js@latest
Enter fullscreen mode Exit fullscreen mode

Pro Tips for OWASP Dependency Check

  1. Always use the NVD API key: Scans are 10x faster
  2. Set a CVSS threshold: Fail builds on critical vulnerabilities (7+)
  3. Suppress false positives: Create a suppression file for known safe cases
  4. Schedule regular scans: Run daily or with every build
  5. Update regularly: Keep the vulnerability database fresh
  6. Use multiple formats: HTML for viewing, JSON for automation

Common Pitfalls and How to Avoid Them

Pitfall 1: "Too many false positives!"

Solution:

  • Configure your tools properly
  • Use suppression files for known safe cases
  • Don't ignore everything - triage issues properly
  • Start with high-severity issues first

Pitfall 2: "Scans take too long!"

Solution:

  • Use incremental analysis (scan only changed code)
  • Run full scans nightly, quick scans on every commit
  • Use the NVD API key for dependency checks
  • Cache dependency databases

Pitfall 3: "Developers ignore security reports"

Solution:

  • Make security visible (dashboards, Slack notifications)
  • Fail builds on critical issues
  • Provide clear remediation guidance
  • Train developers on common vulnerabilities
  • Gamify security fixes (track improvements)

Pitfall 4: "We fixed the code but still got hacked"

Solution:

  • Use all three tools - they complement each other
  • Test in production-like environments
  • Consider manual penetration testing for critical apps
  • Regularly update your tools and databases

Conclusion: Security is a Journey, Not a Destination

You can't prevent every breach, but you can make your application a much harder target. By implementing SAST, DAST, and SCA:

  • You catch 94% of vulnerabilities before production
  • You reduce incident response time from months to days
  • You build a security-first culture in your team
  • You gain peace of mind knowing your code is continuously monitored

Remember: The best time to start was yesterday. The second best time is now.


Additional Resources

Official Documentation:

Practice Targets:


GitHub logo juice-shop / juice-shop

OWASP Juice Shop: Probably the most modern and sophisticated insecure web application

Juice Shop Logo OWASP Juice Shop

OWASP Flagship GitHub release Twitter Follow Subreddit subscribers

CI/CD Pipeline Coverage StatusCypress tests OpenSSF Best Practices GitHub stars Contributor Covenant

The most trustworthy online shop out there. (@dschadow) — The best juice shop on the whole internet! (@shehackspurple) — Actually the most bug-free vulnerable application in existence! (@vanderaj) — First you 😂😂then you 😢 (@kramse) — But this doesn't have anything to do with juice. (@coderPatros' wife)

OWASP Juice Shop is probably the most modern and sophisticated insecure web application! It can be used in security trainings, awareness demos, CTFs and as a guinea pig for security tools! Juice Shop encompasses vulnerabilities from the entire OWASP Top Ten along with many other security flaws found in real-world applications!

Juice Shop Screenshot Slideshow

For a detailed introduction, full list of features and architecture overview please visit the official project page https://owasp-juice.shop

Table of contents


Let's Build Secure Software Together

💬 What's your biggest security challenge? Share in the comments below, and let's build more secure applications together.

Got questions about implementing these tools? Drop them in the comments—I'll respond to every single one.

Found this helpful? Share it with your team and help spread security awareness!


Connect with me:

📧 Email me

Top comments (0)