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:
- No SSL certificate verification control
post()method allows caching of POST requests (unusual/unsafe)- 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:
- No maximum length validation for clipboard text
- No sanitization before saving to history file
- 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:
- Uses
exec_module()which executes arbitrary Python code - No signature verification for plugins
- No sandboxing or permission system
- 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)
PathValidatorclass for path sanitizationInputValidatorclass for input validationDataValidatorclass for data structure validationIntegrityCheckerfor HMAC/hash operations
Recommendations
Immediate Actions (High Priority)
-
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 -
Add clipboard validation:
- Implement max text length limits
- Sanitize clipboard content
-
Implement plugin security:
- Add plugin signature verification
- Create permission manifest system
Medium Priority
-
Enhance HTTP client:
- Add URL scheme validation
- Enable SSL verification by default
- Add request/response size limits
-
Add audit logging:
- Log all file operations outside data directories
- Log plugin loading/unloading
- Log security violations
Low Priority
-
Implement data encryption:
- Encrypt sensitive plugin data at rest
- Encrypt clipboard history
-
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