T09 · Insecure Skill Coding Practices
- Location
sonos_core.py:73- Finding
Shell Command Injection Through the media_dir Parameter
- Content
View full analysis
Vulnerability Details
File Location:
sonos_core.py:73-81
Vulnerability Type: OS command injection
Risk Level: HighVulnerable Code
python if platform.system() == "Windows": # Start server and save PID to file os.system(f'start /b python -m http.server {HTTP_PORT} --directory "{media_dir}"') # On Windows, we can't easily get the PID of start /b, so just track by port # The stop_http_server will use port-based killing as fallback else: # Use nohup to ensure it persists and save PID os.system(f'nohup python3 -m http.server {HTTP_PORT} --directory "{media_dir}" > /tmp/sonos_http.log 2>&1 &')Technical Analysis
The
media_dirargument is interpolated directly into commands executed throughos.system(). Although it is surrounded by double quotes, the value is not escaped for the relevant command shell. A crafted value containing a closing quote and shell control operators can terminate the intended argument and append arbitrary commands.This issue affects both the Windows and Unix-like execution paths. The function is reachable through the public
announce(..., media_dir=...)API. Consequently, any party capable of influencing that argument may be able to execute commands with the privileges of the process running the Skill.Attack Path
- An attacker gains control over, or influences, the
media_dirvalue supplied toannounce(). announce()passes the value tostart_http_server(media_dir).start_http_server()embeds the untrusted value into a shell command.- A crafted quote closes the
--directoryargument, while shell metacharacters append another command. os.system()invokes the platform shell and executes the injected command.- The injected command runs under the account and permissions of the Agent or Skill host.
Impact Assessment
Successful exploitation permits arbitrary local command execution. The att ...[truncated 260 chars]
- An attacker gains control over, or influences, the
- Remediation
View remediation
Remediation Suggestions
- Replace
os.system()withsubprocess.Popen()using an argument array and withoutshell=True. - Resolve
media_dirwithpathlib.Path.resolve()and require it to be an existing directory. - Restrict serving to an explicitly approved media root and reject paths that escape that root.
- Track the returned
Popenobject or PID directly instead of discovering the process through shell commands. - Open log files through Python and pass their handles to
stdoutandstderr.
Example hardened approach:
python from pathlib import Path import subprocess directory = Path(media_dir).expanduser().resolve() if not directory.is_dir(): raise ValueError("Invalid media directory") process = subprocess.Popen( [ "python3", "-m", "http.server", str(HTTP_PORT), "--bind", HTTP_HOST, "--directory", str(directory), ], stdout=log_file, stderr=subprocess.STDOUT, start_new_session=True, )- Replace
