EU-Utility/SECURITY_AUDIT_REPORT.md

7.5 KiB

EU-Utility Security Audit Report

Date: 2026-02-14 Auditor: Security Auditor Agent Scope: /home/impulsivefps/.openclaw/workspace/projects/EU-Utility/


Executive Summary

The EU-Utility codebase contains several security vulnerabilities, primarily around path traversal, insufficient input validation, and unsafe plugin loading. A hardened version exists for some components (data_store_secure.py, screenshot_secure.py) but the original vulnerable versions are still in use.

Overall Risk Level: MEDIUM-HIGH


Findings

🔴 CRITICAL: Path Traversal in data_store.py

File: core/data_store.py
Severity: HIGH
Status: ⚠️ VULNERABLE (Secure version exists but unused)

Issue: The _get_plugin_file() method uses simple string replacement for sanitization:

def _get_plugin_file(self, plugin_id: str) -> Path:
    safe_name = plugin_id.replace(".", "_").replace("/", "_").replace("\\", "_")
    return self.data_dir / f"{safe_name}.json"

Attack Vector: A malicious plugin could use plugin_id="../../../etc/passwd" to escape the data directory.

Fix: Replace with data_store_secure.py which includes:

  • Proper path validation using PathValidator
  • Resolved path verification against base path
  • Security error handling

🔴 HIGH: Path Traversal in screenshot.py

File: core/screenshot.py
Severity: HIGH
Status: ⚠️ VULNERABLE (Secure version exists but unused)

Issue: The save_screenshot() method accepts arbitrary filenames without validation:

def save_screenshot(self, image: Image.Image, filename: Optional[str] = None) -> Path:
    if filename is None:
        timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S_%f")[:-3]
        filename = f"screenshot_{timestamp}.{self._format.lower()}"
    
    # NO VALIDATION HERE
    filepath = self._save_path / filename
    image.save(filepath, ...)

Attack Vector: A plugin could call save_screenshot(image, "../../../malware.exe") to write outside the screenshots directory.

Fix: Replace with screenshot_secure.py which includes:

  • PathValidator.sanitize_filename() usage
  • Resolved path verification
  • Security error handling

🟡 MEDIUM: Insufficient HTTP Client Security

File: core/http_client.py
Severity: MEDIUM
Status: ⚠️ PARTIALLY VULNERABLE

Issues:

  1. No SSL certificate verification control
  2. post() method allows caching of POST requests (unusual/unsafe)
  3. No URL scheme validation (could allow file:// protocol)

Recommendations:

  • Always verify SSL certificates
  • Add URL scheme whitelist (http://, https://)
  • Disable caching for POST by default

🟡 MEDIUM: Unvalidated Clipboard Storage

File: core/clipboard.py
Severity: MEDIUM
Status: ⚠️ VULNERABLE

Issues:

  1. No maximum length validation for clipboard text
  2. No sanitization before saving to history file
  3. History file stored without encryption

Attack Vector: A malicious actor could copy extremely large text (GBs) causing DoS via memory exhaustion.

Recommendations:

  • Add max length limits (e.g., 10KB per entry, 1000 entries max)
  • Sanitize text before storage
  • Consider encrypting sensitive clipboard history

🟠 HIGH: Unsafe Plugin Loading

File: core/plugin_manager.py
Severity: HIGH
Status: ⚠️ VULNERABLE

Issues:

  1. Uses exec_module() which executes arbitrary Python code
  2. No signature verification for plugins
  3. No sandboxing or permission system
  4. No validation of plugin metadata

Attack Vector: A malicious plugin in the user_plugins directory could execute arbitrary code with user privileges.

Recommendations:

  • Implement plugin signature verification
  • Add permission manifest system for plugins
  • Consider using restricted Python execution environment
  • Validate plugin metadata against schema

🟡 LOW: Subprocess Usage

Files: Multiple (window_manager.py, notifications.py, spotify_controller.py, game_reader.py)
Severity: LOW
Status: GENERALLY SAFE

Analysis: Subprocess usage found but:

  • Uses hardcoded, safe commands
  • No user input passed to shell commands
  • Timeout protections in place

No immediate action required but continue to audit any new subprocess additions.


🟢 LOW: No Hardcoded Credentials Found

Status: PASS

Searched for:

  • API keys
  • Passwords
  • Authentication tokens
  • Secret keys

None found in the codebase. Good security practice maintained.


Security Improvements Made

1. data_store_secure.py (EXISTS)

  • Path traversal protection via PathValidator
  • Input validation for plugin IDs and keys
  • Data structure validation
  • Secure backup path validation

2. screenshot_secure.py (EXISTS)

  • Filename sanitization
  • Path resolution validation
  • Region coordinate validation
  • Window handle validation

3. security_utils.py (EXISTS)

  • PathValidator class for path sanitization
  • InputValidator class for input validation
  • DataValidator class for data structure validation
  • IntegrityChecker for HMAC/hash operations

Recommendations

Immediate Actions (High Priority)

  1. Replace vulnerable modules with secure versions:

    mv core/data_store.py core/data_store_vulnerable.py
    mv core/data_store_secure.py core/data_store.py
    
    mv core/screenshot.py core/screenshot_vulnerable.py
    mv core/screenshot_secure.py core/screenshot.py
    
  2. Add clipboard validation:

    • Implement max text length limits
    • Sanitize clipboard content
  3. Implement plugin security:

    • Add plugin signature verification
    • Create permission manifest system

Medium Priority

  1. Enhance HTTP client:

    • Add URL scheme validation
    • Enable SSL verification by default
    • Add request/response size limits
  2. Add audit logging:

    • Log all file operations outside data directories
    • Log plugin loading/unloading
    • Log security violations

Low Priority

  1. Implement data encryption:

    • Encrypt sensitive plugin data at rest
    • Encrypt clipboard history
  2. Add rate limiting:

    • Rate limit screenshot captures
    • Rate limit API calls per plugin

Security Test Cases

# Test Path Traversal Protection
def test_path_traversal():
    # Should raise SecurityError
    try:
        data_store._get_plugin_file("../../../etc/passwd")
        assert False, "Path traversal not blocked!"
    except SecurityError:
        pass  # Expected

# Test Filename Sanitization
def test_filename_sanitization():
    # Should sanitize dangerous characters
    safe = PathValidator.sanitize_filename("../../../test.txt")
    assert ".." not in safe
    assert "/" not in safe

# Test Input Validation
def test_clipboard_limits():
    # Should reject oversized input
    large_text = "x" * (10 * 1024 * 1024)  # 10MB
    result = clipboard_manager.copy(large_text)
    assert result == False  # Should fail

Conclusion

The EU-Utility project has a solid security foundation with security_utils.py providing comprehensive validation utilities. However, the original vulnerable modules are still in use instead of the hardened versions.

Priority 1: Switch to the secure versions of data_store and screenshot modules.

Priority 2: Implement plugin sandboxing and signature verification.

With these changes, the project risk level can be reduced from MEDIUM-HIGH to LOW-MEDIUM.


Report generated by Security Auditor Agent
EU-Utility Security Audit 2026