T09 · Insecure Skill Coding Practices
- Location
scripts/schedule_call.py:196- Finding
OS Command Injection Through Scheduled Call Content
- Content
View full analysis
Vulnerability Details
File Location:
scripts/schedule_call.py:196-209
Vulnerability Type: OS command injection through unsafe shell command construction
Risk Level: CriticalVulnerable Code
python def schedule_task(contact: str, phone_content: str, delay_seconds: int, time_desc: str): """Create a scheduled task; phone_content is the message played during the call.""" script_dir = os.path.dirname(__file__) main_script = os.path.join(script_dir, "main.py") python_exe = get_python_executable() if delay_seconds > 0: cmd = f"(sleep {delay_seconds} && {python_exe} {main_script} '{contact}' '{phone_content}' 0) &" subprocess.Popen(cmd, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) return True else: subprocess.run([python_exe, main_script, contact, phone_content, "0"]) return TrueTechnical Analysis
The delayed-execution branch constructs a shell command by directly interpolating
phone_contentinto a single-quoted argument and then executes that command withshell=True.phone_contentoriginates from the command supplied by the user. Although parsing removes certain time expressions and digits, it does not reject or escape shell metacharacters such as single quotes, semicolons, parentheses, redirection operators, or comment characters. An attacker can therefore terminate the quoted argument and append arbitrary shell commands.The immediate-call branch correctly uses an argument list, but delayed calls use an unsafe shell string. Suppressing standard output and standard error also makes exploitation and execution failures less visible.
Attack Path
- An attacker submits a delayed outbound-call instruction containing a recognized contact and malicious message content.
parse_command()extracts the attacker-controlled text asphone_content.schedule_task()i ...[truncated 908 chars]
- Remediation
View remediation
Remediation Suggestions
-
Remove
shell=Trueand never construct commands through string interpolation. -
Perform delayed execution in Python or use a scheduler that accepts an argument array.
-
Invoke the target script with a fixed argument list:
python import time def run_delayed_call(contact, phone_content, delay_seconds): time.sleep(delay_seconds) subprocess.run( [python_exe, main_script, contact, phone_content, "0"], check=True, ) -
If a detached process is required, create a small Python worker that receives validated arguments without invoking a shell.
-
Validate message length and allowed characters as defense in depth, but do not rely on filtering as the primary fix.
-
Log scheduling and execution failures securely rather than discarding both output streams.
-
Run the Skill under a dedicated, least-privileged operating-system account with restricted filesystem and network access.
-
