T09 · Insecure Skill Coding Practices
- Location
scripts/wmserver_20260327.py:55- Finding
Unauthenticated WM_COPYDATA Interface Permits Speech Injection and Forced Shutdown
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a coherent local Windows text-to-speech helper, but it uses a long-running local message server with unauthenticated control messages and PowerShell execution that users should review before installing.
Install only if you are comfortable running a local Windows helper that can be messaged by other same-session local processes and that invokes PowerShell for speech. Prefer using it in a limited environment, pin pywin32, avoid sending secrets while TTS mode is enabled, and remove or ignore the debug test script unless you need it.
scripts/wmserver_20260327.py:55Unauthenticated WM_COPYDATA Interface Permits Speech Injection and Forced Shutdown
SKILL.md:73Runtime Dependency Is Installed Without Version or Integrity Pinning
The skill instructs the agent to launch local Python scripts, send WM_COPYDATA messages, and read/write local config files, but it declares no tool scope or allowed-tools constraints. That creates a real capability mismatch: an agent may be induced to use shell and filesystem access without explicit permission boundaries, increasing the risk of unintended command execution or local state modification.
This markdown file contains natural-language instructions entirely in Chinese, including the trigger phrases and operating rules, with no indication that users may choose another language. Under the policy rule for language/locale constraints, forcing a specific language without user opt-in is a natural-language policy violation.
Received message content is logged to a persistent local debug file without notice, consent, minimization, or access controls. Because the skill is designed to receive and speak AI replies, the logged text may contain sensitive prompts, personal data, secrets, or other private content, causing unintended data retention and disclosure to other local users or software.
The code launches PowerShell with a dynamically constructed command string and inserts untrusted WM_COPYDATA text into the script passed to -c. Replacing single quotes is not sufficient to guarantee safe PowerShell quoting across all input forms, and the use of -ExecutionPolicy Bypass further weakens defenses. In this skill’s context, any local process able to send the window message can feed attacker-controlled text into this path, creating a realistic local code-injection risk.
except: pass
e = t.replace("'","''")
log(f"Play vol={cv} text={t[:20]}")
subprocess.run(
["powershell","-ExecutionPolicy","Bypass","-NoProfile","-c",
"Add-Type -AssemblyName System.Speech; "
"$s=New-Object System.Speech.Synthesis.SpeechSynthesizer; "
The code spawns PowerShell to perform TTS and passes user-controlled text into a dynamically constructed script. Although single quotes in the spoken text are doubled, the design still grants the skill unnecessary script-execution capability and relies on fragile command construction instead of a native API call. In a message-driven local service, this broadens the attack surface and can be abused if future changes weaken escaping or if other inputs become script-controlled.
f"$s.Rate={cs};$s.Volume={cv};$s.Speak('{t.replace(chr(39),chr(39)+chr(39))}')"
)
b64 = base64.b64encode(cmd.encode("utf-16-le")).decode()
subprocess.run(
["powershell","-ExecutionPolicy","Bypass","-NoProfile",
"-EncodedCommand", b64],
timeout=30, capture_output=True,
Launching PowerShell with -ExecutionPolicy Bypass is unnecessary for a local TTS helper and creates a more capable execution primitive than the feature requires. Even if the current command is intended only for speech synthesis, using a bypassed scripting host means any bug in message handling or future code changes could turn this into arbitrary script execution more easily than if a direct speech library were used.