Back to skill

Security audit

toutiaoAutoPublish

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real Toutiao publishing automation tool, but it can post under the active logged-in account while silently changing content and without a final confirmation step.

Install only if you are comfortable with automation using your logged-in Toutiao browser session to make public posts. Review and modify the script first to require explicit confirmation, publish exactly the supplied text, use an isolated browser profile, pin dependencies, and avoid interpolating content into JavaScript.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/toutiao_publish.py:341
Finding
JavaScript Injection Through User-Controlled Post Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/toutiao_publish.py:341-350` **Vulnerability Type**: Browser-context JavaScript injection **Risk Level**: High ### Vulnerable Code ```python js_content = content.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('\n', '<br>') page.evaluate(f''' () => {{ const editor = document.querySelector('div[contenteditable="true"]'); if (editor) {{ editor.innerHTML = `{js_content}`; editor.dispatchEvent(new Event('input', {{ bubbles: true }})); editor.dispatchEvent(new Event('change', {{ bubbles: true }})); }} }} ''') ``` ### Technical Analysis The post content is controlled through a positional command-line argument or a user-selected file. Although the code replaces HTML metacharacters, it interpolates the resulting value directly into a JavaScript template literal passed to `page.evaluate()`. HTML escaping does not make data safe for a JavaScript template-literal context. In particular, the code does not escape backticks, backslashes, or `${...}` template expressions. An attacker can therefore supply content that terminates the template literal or introduces a template expression, causing arbitrary JavaScript to execute in the authenticated Toutiao page. The injected code executes inside the browser origin rather than as native operating-system code. Nevertheless, it inherits access to the page DOM and the authenticated web session available to scripts executing in that origin. ### Attack Path 1. An attacker convinces the user or calling agent to publish attacker-controlled text, or supplies a post-content file. 2. The content contains a JavaScript template-literal payload using a backtick or `${...}` expression. 3. The script performs HTML escaping, but the JavaScript control characters remain intact. 4. The content is inserted into the Python f-string used to construct the `page.evaluate()` program. 5. Playwr ...[truncated 833 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Do not construct executable JavaScript by interpolating post content. Pass untrusted data as a separate Playwright argument or use locator text-entry APIs. A safer pattern is: ```python page.evaluate( """({editor, content}) => { editor.innerText = content; editor.dispatchEvent(new Event('input', {bubbles: true})); editor.dispatchEvent(new Event('change', {bubbles: true})); }""", { "editor": input_box.element_handle(), "content": content, }, ) ``` Where supported by the editor, prefer `input_box.fill(content)` or `input_box.press_sequentially(content)`. Avoid assigning untrusted data to `innerHTML`; use `innerText` or `textContent` unless HTML formatting is explicitly required. Add regression tests containing backticks, backslashes, `${...}` expressions, HTML tags, Unicode text, and multiline input to verify that all supplied content remains data and cannot affect JavaScript syntax. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:24
Finding
Unpinned Dependency Installation Into a System-Managed Python Environment<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:24-25` **Vulnerability Type**: Unsafe and unpinned dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash pip3 install playwright --break-system-packages playwright install chromium ``` ### Technical Analysis The installation instructions retrieve the latest available Playwright package and associated browser artifact without pinning an expected version or verifying package hashes. Consequently, the installed code can change after the Skill has been reviewed. The `--break-system-packages` option bypasses protections intended to prevent `pip` from modifying a Python environment managed by the operating system or another package manager. This increases the chance of dependency conflicts and modifies a broader environment than the Skill requires. No malicious package, alternate package index, or typosquatted dependency was identified in the reviewed project. The risk arises from implicit trust in mutable upstream artifacts and from installation into the system-managed environment. ### Attack Path 1. A user follows the documented setup instructions. 2. `pip3` resolves whichever Playwright release is current at installation time. 3. The package and its dependency graph are downloaded without project-enforced version or hash verification. 4. Package installation modifies the system-managed Python environment under the user's privileges. 5. A compromised upstream release, dependency, repository account, or distribution channel could execute or install malicious code during installation or later import. 6. Even without a supply-chain compromise, incompatible future releases may overwrite dependencies or destabilize other applications using the same Python environment. ### Impact Assessment A compromised dependency could execute with the privileges of the user running the installation and could access files, browser data, network resources, and other assets available to that u ...[truncated 343 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Create and use a dedicated virtual environment instead of bypassing system-package protections: ```bash python3 -m venv .venv . .venv/bin/activate python -m pip install --require-hashes -r requirements.txt python -m playwright install chromium ``` Pin Playwright and all transitive Python dependencies to reviewed versions in a lock file. Include cryptographic hashes and configure the expected official package index explicitly. Record or pin the required Playwright browser revision where practical. Remove `--break-system-packages` from the instructions. Document a controlled update process in which dependency upgrades are reviewed, tested, and deliberately accepted rather than automatically resolved at installation time. ]]>

other

Warning
Location
scripts/toutiao_publish.py:238
Finding
Silent Modification of User-Supplied Publication Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/toutiao_publish.py:238-239` **Vulnerability Type**: Unauthorized content modification **Risk Level**: Medium ### Vulnerable Code The following is an English-normalized representation of the complete affected branch; the source contains a fixed non-English promotional persona paragraph at line 239: ```python if len(content) < 100: content += "\n\n[fixed promotional persona paragraph about the AI assistant and the platform]" ``` ### Technical Analysis When the supplied post contains fewer than 100 characters, the script silently appends a fixed promotional and persona-oriented paragraph. This behavior is not disclosed in the usage documentation, and the user is not shown the final post or asked to approve it before the script clicks the publication button. This is a content-integrity issue because the authenticated account publishes materially different text from what the user supplied. The appended text is not necessary for browser automation and is unrelated to safely validating a platform length requirement. The same behavior also applies when no content is supplied because the function substitutes a predefined default post before publication. ### Attack Path 1. The user supplies a post containing fewer than 100 characters. 2. The script detects the short length. 3. It appends a fixed promotional persona paragraph without displaying the final content for approval. 4. The modified content is inserted into the Toutiao editor. 5. The script clicks the publication button while using the user's authenticated browser session. 6. The additional statement is published under the user's account as though the user authored or approved it. ### Impact Assessment The issue can cause unauthorized statements to be published under the user's identity. Potential consequences include reputational harm, inaccurate attribution, policy violations, unwanted promotion, and loss of control over account cont ...[truncated 238 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Remove the automatic paragraph insertion and publish exactly the content supplied by the user. If the platform enforces a minimum content length, validate the input and stop with a clear error rather than fabricating additional text: ```python if content is None: raise ValueError("Post content is required.") if len(content) < MINIMUM_LENGTH: raise ValueError( f"Post content must contain at least {MINIMUM_LENGTH} characters." ) ``` Before performing the irreversible publication action, display the complete final text, selected topics, image path, target account, and destination. Require explicit confirmation unless the user has deliberately enabled a documented non-interactive mode. Any default post content should be opt-in, clearly documented, and never published merely because the caller omitted an argument. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The description understates the real behavior: it reuses an authenticated Chrome session via remote debugging, reads local files, and performs real account actions beyond a simple 'publisher' description. This mismatch is dangerous because users may invoke it without understanding that it can control a logged-in browser session and publish publicly using existing credentials.

Ssd 4

High
Confidence
99% confidence
Finding
The default post text explicitly says the agent used the owner's account on its own to explore and publish successfully. That framing normalizes unauthorized account use and, combined with automatic publishing behavior, strongly suggests the code is designed to post under the user's identity without meaningful authorization boundaries.

Lp3

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding
The skill does not declare any explicit tool scope or permissions even though its documented behavior includes reading local files for post content and images. Missing scope declarations reduce user and platform visibility into what the skill can access, making accidental overreach or misuse harder to detect and govern.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The trigger conditions are broad enough that normal conversational phrases like '发布头条' or generic requests to publish social content may activate a skill that performs a real external action. Over-broad activation increases the chance of unintended invocation, especially given that the target action is posting to a public account.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill lacks a clear warning that it will make a real public post to the user's already logged-in Toutiao account. In this context, silent use of an authenticated session is especially risky because a mistaken invocation or deceptive input can cause irreversible public publication, reputational harm, or policy/account issues.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
When the supplied content is under 100 characters, the tool silently appends a long AI-generated message, materially changing what will be posted. In a publishing tool, modifying user intent without explicit approval is dangerous because it can cause unwanted statements to be published under the user's identity.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The tool reuses an existing logged-in Chrome session to publish on behalf of whichever account is active, without a strong warning or an explicit account-selection step. In the context of a social-media publishing skill, this makes unintended posting significantly more dangerous because the action is taken under the user's real authenticated identity.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The script attaches to an existing Chrome instance over the DevTools protocol and then operates inside a reused browser context. That gives the code access not only to the intended Toutiao session but potentially to all cookies, tabs, and authenticated state in that browser profile, expanding the blast radius well beyond simple content publishing.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The script clicks the final publish button immediately once it finds it, with no last-step confirmation showing the exact account, content, image, and options being posted. Because this acts on a real social-media account, accidental or manipulated invocation can directly create unauthorized public posts.

Static analysis

No suspicious patterns detected.