Vulnerability Root Cause Analyzer
Analyze vulnerable code to identify the underlying root causes that enable security vulnerabilities.
Overview
Security vulnerabilities are symptoms of deeper issues in code design and implementation. This skill analyzes vulnerable code to identify:
- Violated assumptions - What the code assumes but doesn't verify
- Incorrect invariants - Properties that should hold but don't
- Missing checks - Validation that should exist but is absent
- Unsafe interactions - How components interact unsafely
- Design flaws - Architectural issues that enable vulnerabilities
The goal is to understand WHY the vulnerability exists, not just WHAT it is.
Root Cause Analysis Workflow
Vulnerable Code
↓
Identify Vulnerability Type
↓
Trace Attack Vector
↓
Analyze Assumptions
↓
Check Invariants
↓
Identify Missing Checks
↓
Examine Component Interactions
↓
Determine Root Cause
↓
Explain Exploitation Chain
Analysis Process
Step 1: Identify Vulnerability Type
Classify the vulnerability:
Common types:
- Buffer overflow
- SQL injection
- Cross-site scripting (XSS)
- Authentication bypass
- Privilege escalation
- Use-after-free
- Race condition
- Integer overflow
Step 2: Trace Attack Vector
Understand how an attacker exploits the vulnerability:
Questions:
- What input triggers the vulnerability?
- What operations are performed?
- What security boundary is crossed?
- What is the impact?
Step 3: Analyze Assumptions
Identify implicit assumptions in the code:
Common assumptions:
- Input is trusted
- Buffer is large enough
- Integer won't overflow
- Pointer is valid
- User is authenticated
- Data is sanitized
Check: Are these assumptions verified?
Step 4: Check Invariants
Verify properties that should always hold:
Common invariants:
- Buffer bounds respected
- Pointers valid before dereference
- Authentication required for sensitive operations
- Data sanitized before use
- Resources properly released
Check: Do these invariants hold in all code paths?
Step 5: Identify Missing Checks
Find validation that should exist:
Common missing checks:
- Input validation
- Bounds checking
- Null pointer checks
- Authentication checks
- Authorization checks
- Type validation
- Size limits
Step 6: Examine Component Interactions
Analyze how components interact:
Unsafe patterns:
- Trusting data from untrusted source
- Passing unsanitized data between components
- Shared mutable state without synchronization
- Missing error propagation
- Inconsistent security policies
Step 7: Determine Root Cause
Identify the fundamental issue:
Root cause categories:
- Design flaw
- Implementation error
- Missing security control
- Incorrect assumption
- Inadequate validation
- Unsafe API usage
Root Cause Categories
For detailed root cause patterns, see [references/root_causes.md](references/root_causes.md).
Categories include:
- Trust boundary violations
- Input validation failures
- Memory safety violations
- Authentication/authorization flaws
- Race conditions and TOCTOU
- Cryptographic misuse
Vulnerability Patterns
For common vulnerability patterns and their root causes, see [references/vulnerability_patterns.md](references/vulnerability_patterns.md).
Patterns include:
- Injection vulnerabilities
- Memory corruption
- Logic flaws
- Information disclosure
- Denial of service
Example Analysis
Input: Buffer overflow vulnerability
// Vulnerable code
void process_input(char *user_input) {
char buffer[64];
strcpy(buffer, user_input); // VULNERABLE
process(buffer);
}
Output: Root cause analysis
# Vulnerability Root Cause Analysis
## Vulnerability Summary
**Type:** Buffer Overflow (CWE-120)
**Location:** process_input() function
**Severity:** Critical
**Impact:** Arbitrary code execution
## Vulnerability Description
The `strcpy` function copies user-controlled input into a fixed-size buffer
without checking the input length, allowing an attacker to overflow the buffer
and overwrite adjacent memory.
## Attack Vector
1. Attacker provides input longer than 64 bytes
2. `strcpy` copies entire input into 64-byte buffer
3. Excess bytes overflow into adjacent stack memory
4. Attacker can overwrite return address
5. Control flow hijacked to attacker-controlled code
## Root Cause Analysis
### Primary Root Cause: Violated Assumption
**Assumption:** Input length ≤ 64 bytes
**Reality:** Input length is unbounded and attacker-controlled
**Violation:** Code assumes input fits in buffer without verification
**Why this assumption exists:**
- Developer may have expected input from trusted source
- May have assumed earlier validation (that doesn't exist)
- May not have considered malicious input
**Why it's violated:**
- No length check before `strcpy`
- `strcpy` doesn't enforce bounds
- Input comes from untrusted source (user)
### Secondary Root Cause: Missing Security Control
**Missing Control:** Input length validation
**Should exist:** Before copying to fixed-size buffer
**Impact:** Allows unbounded copy operation
**What should be present:**
if (strlen(user_input) >= sizeof(buffer)) { // Handle error return; }
### Tertiary Root Cause: Unsafe API Usage
**Unsafe API:** `strcpy`
**Why unsafe:** No bounds checking
**Safe alternative:** `strncpy`, `strlcpy`, or `snprintf`
**API characteristics:**
- `strcpy` copies until null terminator
- No way to specify maximum length
- Inherently unsafe for untrusted input
## Invariant Violations
### Invariant 1: Buffer Bounds
**Expected:** `buffer[0]` through `buffer[63]` only
**Violated:** Writes beyond `buffer[63]`
**Consequence:** Stack corruption
### Invariant 2: Control Flow Integrity
**Expected:** Function returns to caller
**Violated:** Return address overwritten
**Consequence:** Arbitrary code execution
## Missing Checks
1. **Input length validation**
- Location: Before `strcpy` call
- Check: `strlen(user_input) < sizeof(buffer)`
- Impact: Prevents overflow
2. **Buffer bounds enforcement**
- Location: During copy operation
- Check: Use bounded copy function
- Impact: Limits copy to buffer size
3. **Input source validation**
- Location: At trust boundary
- Check: Verify input from trusted source
- Impact: Reduces attack surface
## Component Interaction Analysis
### Trust Boundary Violation
[Untrusted Input] → [No Validation] → [Trusted Buffer]
**Issue:** Data crosses trust boundary without validation
**Components:**
- **User input:** Untrusted, attacker-controlled
- **process_input():** Assumes trusted input
- **buffer:** Expects bounded data
**Unsafe interaction:**
- Untrusted data used directly in memory operation
- No sanitization or validation at boundary
- Downstream code assumes data is safe
## Exploitation Chain
1. **Entry point:** User provides input
2. **Missing check:** No length validation
3. **Unsafe operation:** `strcpy` with unbounded input
4. **Memory corruption:** Buffer overflow
5. **Control flow hijack:** Return address overwritten
6. **Code execution:** Attacker code runs
**Each link in chain is necessary:**
- Remove any link → exploitation fails
- All links present → exploitation succeeds
## Systemic Issues
### Design Flaw
**Issue:** Fixed-size buffer for variable-length input
**Better design:** Dynamic allocation or streaming
### Implementation Error
**Issue:** Using unsafe `strcpy` function
**Better implementation:** Use safe alternatives
### Missing Security Layer
**Issue:** No input validation layer
**Better architecture:** Validate at trust boundary
## Recommended Fixes
### Fix 1: Input Validation (Immediate)
void process_input(char *user_input) { char buffer[64]; if (strlen(user_input) >= sizeof(buffer)) { // Log error and reject return; } strcpy(buffer, user_input); process(buffer); }