Back to skill

Security audit

WeChat Tietu Draft

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it says, but it also controls a logged-in WeChat browser session while saving sensitive logs/screenshots and can force-kill unrelated local processes.

Install only if you are comfortable with this skill controlling a logged-in WeChat Official Account Chrome session and creating remote drafts. Before use, review or change the port-killing behavior, treat skill.log and mp_login_screenshot.png as sensitive, delete them after runs, and prefer a pinned dependency in an isolated Python environment.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
skill_main.py:588
Finding

Arbitrary Termination of Processes Bound to a User-Selected Port

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
wechat_tietu_draft.py:180
Finding

WeChat Session Data and Browser-Control Endpoints Written to Plaintext Logs

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
skill_main.py:239
Finding

Persistent Capture of Potentially Sensitive WeChat Login or Account Screenshots

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unbounded and Unverified Third-Party Dependency Version

Content
View full analysis
=10.0 ``` The documentation also recommends an unconstrained installation: ```bash pip install websockets ``` ### Technical Analysis The dependency specification accepts every `websockets` release from version 10.0 onward. It has no exact version, upper bound, package hash, or lock-file protection. As a result, two installations performed at different times can obtain materially different code. A future compromised, malicious, or incompatible release could execute with the same privileges as the Skill. This dependency is security-sensitive because it participates directly in communication with the Chrome DevTools Protocol endpoint controlling an authenticated browser session. No evidence was found that the named package is currently malicious. The vulnerability is the absence of dependency reproducibility and integrity controls, not a confirmed compromise of the package itself. ### Attack Path 1. A user installs the Skill dependencies at a later time or through a modified package index. 2. The broad `>=10.0` constraint permits the installer to select an unreviewed future release. 3. The selected package is imported when the Skill starts. 4. Package initialization or runtime code executes under the invoking user's account. 5. A compromised dependency could access process data, files available to the user, and the local authenticated browser-control workflow. ### Impact Assessment A compromised dependency would execute with the privileges of the Skill process and could potentially access: - Input article files. - Environment variables inherited by the process. - Generated logs and screenshots. - Local files accessible to the invoking user. - The Chrome DevTools WebSocket endpoint. - The active authenticated WeChat browser c ...[truncated 145 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (32)

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · skill_main.py (reported line 834)May include surrounding context.

python
if not ensure_chrome_ready_for_draft(port):
        return False
    try:
        child_env = os.environ.copy()
        child_env["CDP_TIETU_CHILD"] = "1"
        child_env["CDP_TIETU_PORT"] = str(port)
        with open(log_file, "w", encoding="utf-8") as f:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documentation declares no explicit tool scope even though the skill clearly relies on shell execution, filesystem access, environment inspection, network connectivity, and browser/session manipulation. This weakens least-privilege enforcement and makes it easier for the skill to be invoked with broader capabilities than users or a host framework may expect, increasing the chance of unintended local or account-affecting actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill description does not prominently warn that it may automatically launch Chrome, attach to a live logged-in WeChat Official Account session, and create or save drafts on a remote service. Because these actions can change account state and publishable content, insufficient disclosure can mislead users or orchestrators into granting consent for automation they do not fully understand.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 92)May include surrounding context.

python
"""本机打开 URL(无 CDP 时打开 mp 首页等)"""
    try:
        if sys.platform == "darwin":
            subprocess.run(["open", url], check=False, timeout=10)
        elif sys.platform == "win32":
            os.startfile(url)  # noqa: S606
        else:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 96)May include surrounding context.

python
elif sys.platform == "win32":
            os.startfile(url)  # noqa: S606
        else:
            subprocess.run(["xdg-open", url], check=False, timeout=10)
    except Exception:
        pass

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill writes browser screenshots to a predictable local file without clearly warning the user that authenticated page contents are being captured. This creates unnecessary local persistence of potentially sensitive publisher-session data and can expose information to other local users or later processes.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 246)May include surrounding context.

python
成功返回绝对路径字符串,失败返回 None。
    """
    try:
        r = subprocess.run(
            ["curl", "-s", f"http://127.0.0.1:{port}/json/list"],
            capture_output=True,
            text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 346)May include surrounding context.

python
for i in range(checks):
        elapsed = i * interval
        try:
            r = subprocess.run(
                ["curl", "-s", f"http://127.0.0.1:{port}/json/list"],
                capture_output=True,
                text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 374)May include surrounding context.

python
def refetch_best_wechat_page(port=DEFAULT_CDP_PORT):
    try:
        r = subprocess.run(
            ["curl", "-s", f"http://127.0.0.1:{port}/json/list"],
            capture_output=True,
            text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 424)May include surrounding context.

python
def refetch_best_wechat_page(port=DEFAULT_CDP_PORT):
    try:
        r = subprocess.run(
            ["curl", "-s", f"http://127.0.0.1:{port}/json/list"],
            capture_output=True,
            text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 492)May include surrounding context.

python
try:
        # 1. 检查调试端口是否响应
        try:
            result = subprocess.run(
                ["curl", "-s", f"http://127.0.0.1:{port}/json/version"],
                capture_output=True,
                text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 508)May include surrounding context.

python
# 2. 获取页面列表
        try:
            result = subprocess.run(
                ["curl", "-s", f"http://127.0.0.1:{port}/json/list"],
                capture_output=True,
                text=True,

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill forcefully frees the chosen CDP port by discovering and killing whatever process currently owns it. That capability is not necessary for creating a draft and creates an unjustified local denial-of-service primitive against unrelated software.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script kills processes occupying the target port without warning or confirmation, violating least surprise and safe automation practices. In practical terms this can disrupt unrelated developer workflows, browsers, proxies, or monitoring agents on the host.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
97% confidence
Finding

This subprocess call is part of logic that enumerates arbitrary processes bound to the configured port and enables later forced termination. In the skill context, killing unrelated local processes exceeds the stated draft-creation purpose and can disrupt other applications or security tooling.

Content

Scanner excerpt · skill_main.py (reported line 592)May include surrounding context.

python
def _chrome_kill_port_pids(port=DEFAULT_CDP_PORT):
    """释放调试端口(macOS/Linux:lsof + kill)。"""
    try:
        r = subprocess.run(
            ["lsof", "-ti", f":{port}"],
            capture_output=True,
            text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

This line forcefully kills every PID listening on the configured port using kill -9, without ownership checks or user confirmation. In context, that can terminate unrelated local applications and cause denial of service or data loss, which is beyond the skill's declared purpose.

Content

Scanner excerpt · skill_main.py (reported line 601)May include surrounding context.

python
return False
        for pid in r.stdout.strip().split():
            try:
                subprocess.run(["kill", "-9", pid], capture_output=True, timeout=2)
            except Exception:
                pass
        time.sleep(2)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 624)May include surrounding context.

python
chrome_cmd = p
            break
    if not chrome_cmd:
        r = subprocess.run(["which", "google-chrome"], capture_output=True, text=True)
        chrome_cmd = r.stdout.strip() if r.returncode == 0 else "google-chrome"
    ts = int(time.time())
    user_data = os.path.expanduser(f"~/.chrome-real-wechat-{ts}")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 641)May include surrounding context.

python
WECHAT_MP_HOME,
    ]
    try:
        subprocess.Popen(
            cmd,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Content

Scanner excerpt · skill_main.py (reported line 650)May include surrounding context.

python
time.sleep(3)
        for i in range(15):
            try:
                with urllib.request.urlopen(
                    f"http://127.0.0.1:{port}/json/version", timeout=3
                ) as resp:
                    if resp.status == 200:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 667)May include surrounding context.

python
def _sr_list_has_page(port):
    try:
        r = subprocess.run(
            ["curl", "-s", f"http://127.0.0.1:{port}/json/list"],
            capture_output=True,
            text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 685)May include surrounding context.

python
def _sr_list_has_page(port):
    try:
        r = subprocess.run(
            ["curl", "-s", f"http://127.0.0.1:{port}/json/list"],
            capture_output=True,
            text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 703)May include surrounding context.

python
def _sr_list_has_page(port):
    try:
        r = subprocess.run(
            ["curl", "-s", f"http://127.0.0.1:{port}/json/list"],
            capture_output=True,
            text=True,

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Content

Scanner excerpt · skill_main.py (reported line 722)May include surrounding context.

python
body = json.dumps(
            {"id": 1, "method": "Page.navigate", "params": {"url": WECHAT_MP_HOME}}
        ).encode()
        req = urllib.request.Request(
            f"http://127.0.0.1:{port}/json/session/{pid}",
            data=body,
            headers={"Content-Type": "application/json"},

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 751)May include surrounding context.

python
"""
    debug_ok = False
    try:
        r = subprocess.run(
            ["curl", "-s", f"http://127.0.0.1:{port}/json/version"],
            capture_output=True,
            text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · skill_main.py (reported line 840)May include surrounding context.

python
with open(log_file, "w", encoding="utf-8") as f:
            f.write(f"# Run at {datetime.now().isoformat(timespec='seconds')} file={Path(file_path).name}\n")
            f.flush()
            result = subprocess.run(
                [sys.executable, str(draft_script), str(file_path)],
                stdout=f,
                stderr=subprocess.STDOUT,