Post

Static Analysis (SAST)

Static Analysis (SAST)

Overview

As penetration testers and software engineers, we often obsess over dynamic attacks—SQL injection payloads, XSS vectors, and runtime exploits. But what if you could catch the vulnerability before the code is even compiled?

Enter Static Analysis (often called SAST in the security world). It’s not just a “spellchecker” for your code; it is an automated way to reason about the runtime properties of your software without ever hitting the “Run” button.

In this post, we’ll dive into how static analysis works, why it’s critical for preventing security debt, and look at real code examples that tools catch.

What is it, really?

Think of Dynamic Analysis (DAST) as a crash test: you drive the car into a wall to see if the airbag deploys. Static Analysis, on the other hand, is like a blueprint review: an engineer looks at the schematics and says, “Hey, you forgot to draw the line connecting the airbag sensor to the inflator.”

The goal is to find problems that are computationally complex or “undecidable” to find during manual testing. These tools scan your source code to detect:

  • Security Vulnerabilities: Weak cryptography, injection flaws.
  • Reliability Issues: Resource leaks, null pointer dereferences.
  • Bad Practices: Violating coding standards (like MISRA or Google Style Guides).

The “False Positive” Dilemma

If you’ve ever run a security scan, you know the pain of sifting through 500 warnings where 490 are useless. This happens because static analysis relies on approximations.

To save time, the analyzer sacrifices some precision. This leads to two outcomes you need to understand:

  1. False Positive: The tool flags code as vulnerable, but it’s actually safe. This causes “alert fatigue”.
  2. False Negative: The tool says the code is clean, but a bug exists. This is dangerous in security contexts.

Pro Tip: Don’t aim for zero warnings immediately. Configure your tools to filter by “Severity” or specific vulnerability categories first.

image.png

Code in Action: What the Scanner Sees

Let’s look at two common patterns that static analysis tools (like SonarQube, SpotBugs, or Coverity) excel at finding.

1. The Resource Leak (Availability / DoS Risk)

A common issue in Java/C++ is failing to close resources (files, sockets, database connections). In a security context, an attacker could trigger this path repeatedly to exhaust server resources, causing a Denial of Service (DoS).

The Vulnerable Pattern:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void readConfidentialData(String path) {
    try {
        // SCANNERS catch this: "Resource not closed on all paths"
        FileInputStream fis = new FileInputStream(path); 
        Scanner scanner = new Scanner(fis);
        
        // Imagine an exception happens here while parsing
        String secret = scanner.nextLine(); 
        
        scanner.close(); // If line above fails, this never runs!
    } catch (IOException e) {
        System.out.println("Failed to read secrets.");
    }
}

The Static Analysis Fix: The tool identifies that the .close() method is not reachable in the catch block. It forces you to use a finally block or “try-with-resources”.

1
2
3
4
5
6
7
8
9
10
11
public void readConfidentialData(String path) {
    // The Fix: Auto-closing resource
    try (FileInputStream fis = new FileInputStream(path);
         Scanner scanner = new Scanner(fis)) {
        
        String secret = scanner.nextLine(); 
        // Resource closes automatically, even on crash.
    } catch (IOException e) {
        System.out.println("Failed to read secrets.");
    }
}

2. The Null Pointer Dereference (Reliability / Crash)

While often seen as just a “bug,” a Null Pointer Exception (NPE) is a reliability flaw. If an unauthenticated user can crash your API by sending a missing field, you have an Availability vulnerability.

The Vulnerable Pattern:

1
2
3
4
5
6
7
8
public void processUser(User user) {
    // Static Analysis Flag: "user" might be null here
    String username = user.getName(); 
    
    if (user != null) {
        System.out.println("Logged in: " + username);
    }
}

What the Tool Sees: The analyzer constructs a Control Flow Graph (CFG). It notices you checked if (user != null) after you already accessed user.getName(). This logical inconsistency is a classic pattern tools like Infer or SpotBugs catch immediately.

Integrating into the Workflow (DevSecOps)

The biggest mistake teams make is running these scans only before a release. By then, the “Technical Debt” is too high.

To make this useful for cybersecurity:

  1. Shift Left: Integrate the scanner into your CI/CD pipeline (Jenkins, GitHub Actions).
  2. Block the Build: If a “High Severity” security vulnerability is found, fail the build. Don’t let the code merge.
  3. Code Review: Use the scanner’s report during code review (Pull Requests). It acts as an automated reviewer that never gets tired.

*Integrating Static Analysis checks (SAST) into the commit phase prevents vulnerabilities from reaching production.*

Integrating Static Analysis checks (SAST) into the commit phase prevents vulnerabilities from reaching production.

Conclusion

Static analysis isn’t a silver bullet—it won’t find every logical flaw or architectural vulnerability. However, it is the most cost-effective way to eliminate entire classes of bugs (like resource leaks and null pointers) before they ever become security incidents.

For us in the security field, it’s about reducing the attack surface. Every bug fixed by a static analyzer is one less foothold for an attacker.

This post is licensed under CC BY 4.0 by the author.