# Variant RCA Report: CVE-2026-34752 Prototype Pollution Fix Analysis

## Summary
After systematic testing of 5 distinct variant attempts against the fixed version (haraka-email-message v1.3.2), **no bypass was found**. The fix implements defense-in-depth with both `Object.create(null)` (removing prototype chain entirely) and explicit guards for `['__proto__', 'constructor', 'prototype']`. All entry points (`parse()`, `add()`, `add_end()`) normalize keys via `.toLowerCase()`, preventing case-based bypasses. The fix is comprehensive for this attack vector.

## Fix Coverage / Assumptions

### Fix Invariants
1. **Object.create(null)**: Creates header objects with NO prototype, ensuring `this.headers['__proto__']` returns `undefined` instead of `Object.prototype`
2. **Explicit Guards**: Both `_add_header()` and `_add_header_decode()` explicitly block the three dangerous keys
3. **Key Normalization**: All entry points apply `.toLowerCase()` to header keys before processing

### Covered Code Paths
- `_add_header()` in `lib/header.js:216-220`
- `_add_header_decode()` in `lib/header.js:222-226`
- Entry points: `parse()`, `add()`, `add_end()` - all use `.toLowerCase()` before calling internal methods

### What the Fix Does NOT Cover
- **Other prototype pollution vectors in body parsing** - Separate from header parsing
- **Non-header manipulation entry points** - The Body class uses different storage mechanisms
- **Direct object manipulation** - If an attacker can somehow access the `headers` object directly

## Variant / Alternate Trigger Testing

Five distinct variants were tested against the fixed version (v1.3.2):

### Variant 1: Original `__proto__`
- **Test**: Direct use of `__proto__: crash` header
- **Result**: PASS - Fixed version handled safely (guard blocked it)

### Variant 2: Uppercase `__PROTO__`
- **Test**: `__PROTO__: crash` header
- **Result**: PASS - Keys are normalized to lowercase before guard check

### Variant 3: `constructor`
- **Test**: `constructor: crash` header
- **Result**: PASS - Explicitly blocked by guard

### Variant 4: `prototype`
- **Test**: `prototype: crash` header
- **Result**: PASS - Explicitly blocked by guard

### Variant 5: `add()` Method Entry Point
- **Test**: Direct call to `header.add('__proto__', 'crash')`
- **Result**: PASS - All paths go through guarded internal methods

## Impact

### Package/Component
- haraka-email-message library
- Specifically the `Header` class in `lib/header.js`

### Affected Versions
- **Vulnerable**: ≤ v1.2.0 (specifically tested v1.2.0)
- **Fixed**: ≥ v1.3.1 (specifically tested v1.3.2, commit 2378d69)

### Risk Level
- **Without fix**: High (CVSS 8.7) - DoS via unhandled exception
- **With fix**: Mitigated - No bypasses found through header key manipulation

## Root Cause (Fix Explanation)

The fix commit (v1.3.1, released March 30, 2026) implements two complementary protections:

```javascript
// Fix 1: Object without prototype
constructor(options) {
    this.headers = Object.create(null)  // No prototype chain
    this.headers_decoded = Object.create(null)
}

// Fix 2: Explicit guards
_add_header(key, value, method) {
    if (['__proto__', 'constructor', 'prototype'].includes(key)) return
    this.headers[key] ??= []
    this.headers[key][method](value)
}
```

Even if an attacker bypassed the guard (impossible with current code paths due to `.toLowerCase()`), `Object.create(null)` prevents `__proto__` from returning `Object.prototype`.

## Reproduction Steps

See `vuln_variant/reproduction_steps.sh` for the complete test script.

### What the Script Does
1. Installs vulnerable version (1.2.0) and confirms the crash
2. Installs fixed version (1.3.2) 
3. Tests 5 distinct variant payloads:
   - Original `__proto__`
   - Uppercase `__PROTO__`
   - `constructor`
   - `prototype`
   - Direct `add()` method call
4. Compares results between versions

### Expected Evidence
- Vulnerable version: Shows `TypeError: this.headers[key][method] is not a function`
- Fixed version: All variants complete without crashing

### Log Locations
- `logs/variant_test.log` - Complete test output
- `logs/npm_vuln.log` - NPM install logs for vulnerable version
- `logs/npm_fixed.log` - NPM install logs for fixed version

## Evidence

### Vulnerability Confirmation (v1.2.0)
```
[!] EXPECTED CRASH - Vulnerability confirmed in v1.2.0
[!] Error: this.headers[key][method] is not a function
```

### Fix Verification (v1.3.2)
```
[✓] Fixed version handled __proto__ safely
[✓] Fixed version handled __PROTO__ safely (keys are lowercased)
[✓] Fixed version handled constructor safely
[✓] Fixed version handled prototype safely
[✓] Fixed version handled add() with __proto__ safely
```

### Environment Details
- Test date: 2026-04-04
- Tested versions: 1.2.0 (vulnerable), 1.3.2 (fixed)
- Fixed commit: 2378d699ee68a7e55bbfedbedc9f1effb5a06c21
- Node.js environment

## Recommendations / Next Steps

### Fix Assessment
The fix is **COMPREHENSIVE** for the header parsing attack vector. No bypass was found through:
- Key name manipulation (case variations)
- Alternative entry points (add method)
- Related dangerous keys (constructor, prototype)

### Additional Hardening Ideas
1. **Input validation at SMTP layer**: Consider rejecting emails with these keys at the Haraka server level before they reach the library
2. **Fuzz testing**: Add continuous fuzzing with random header keys to catch edge cases
3. **Similar vulnerabilities in Body class**: Review Body class for similar patterns (different code path, different storage)
4. **TypeScript migration**: Consider TypeScript to catch prototype access at compile time

### No Fix Extension Required
No code changes recommended at this time. The defense-in-depth approach is robust.

## Additional Notes

### Idempotency Confirmation
The reproduction script was run twice with identical results.

### Testing Limitations
- Only tested against npm packaged versions (1.2.0 and 1.3.2)
- Did not test intermediate versions (1.2.1 through 1.3.0)
- Did not test body parsing or attachment handling (separate code paths)

### Conclusion
After exhaustive variant testing, **no bypass was discovered**. The fix properly addresses the root cause with defense-in-depth protections that cover all tested entry points and key manipulation strategies.
