Back to skill

Security audit

抖音爬虫V2

Security checks for vulnerabilities and agentic risk

Overview

This Douyin scraper is not clearly malicious, but it can send searches to Brave and return synthetic results while presenting itself as a scraper, so it needs review before installation.

Install only if you are comfortable with browser automation, external search fallback, and possible synthetic results. Use an isolated, unprivileged environment; avoid exposing unrelated environment secrets; pin dependencies; and treat returned data as unverified unless the skill clearly reports that it came from real Douyin pages.

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 (2)

T08 · Insecure Dependencies

Warning
Location
install_playwright_docker.py:30
Finding

Unpinned Dependencies and Unofficial Browser Binary Mirrors

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1; install.sh:41-42; install_playwright_docker.py:30-37
Vulnerability Type: Supply-chain exposure through unpinned dependencies and unsafe download sources
Risk Level: Medium

Complete Code Snippets

requirements.txt:1

text
playwright>=1.40.0

install.sh:41-42

bash
pip install --upgrade pip
pip install playwright

install_playwright_docker.py:30-37

python
env = os.environ.copy()
env.setdefault("PLAYWRIGHT_DOWNLOAD_HOST", "https://npmmirror.com/mirrors/playwright")
env.setdefault("PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST", "https://cdn.npmmirror.com/binaries/chrome-for-testing")
venv_python = Path("venv/bin/python")
venv_pip = Path("venv/bin/pip")
if not venv_python.exists():
    run([sys.executable, "-m", "venv", "venv"])
run([str(venv_pip), "install", "-r", "requirements.txt"], env=env)
run([str(venv_python), "-m", "playwright", "install", "chromium"], env=env)

Technical Analysis

The Python dependency specification accepts every Playwright release at or above version 1.40.0 rather than selecting a reviewed, reproducible version. The primary installer independently installs the latest available Playwright package and upgrades pip, also without integrity constraints.

The native installation path additionally redirects Playwright and Chromium downloads to third-party mirror domains. No checksum, signature, hash-locked requirements file, or other artifact verification is performed before downloaded code and browser binaries are installed and executed.

This creates a supply-chain risk: dependency resolution may change between installations, and compromise of a package publisher, registry, mirror, or distribution path could substitute malicious package content or a browser executable.

Attack Path

  1. An attacker compromises a configured mirror, relevant package publisher, registry account, or dependency distribution path.
  2. The attacker publishes or ...[truncated 1080 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin Playwright to a reviewed exact version, for example playwright==1.50.0, and update it through a controlled process.
  2. Generate a hash-locked requirements file and install with pip install --require-hashes -r requirements.txt.
  3. Avoid upgrading pip implicitly during normal project installation; pin and manage installer tooling separately.
  4. Use official Playwright browser distribution endpoints instead of third-party mirrors.
  5. If a mirror is operationally necessary, verify every downloaded artifact against a checksum or signature obtained through an independent trusted channel.
  6. Pin container image references by immutable digest rather than a mutable tag.
  7. Add Node.js package metadata and a committed lockfile if the Node implementation remains supported, and use npm ci rather than unrestricted npm install or npx.
  8. Run dependency installation as an unprivileged account in an isolated build environment.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/scraper.py:81
Finding

Chromium Sandbox Disabled While Processing Remote Content

Content
View full analysis

Vulnerability Details

File Location: scripts/scraper.py:81-84; scripts/douyin_scraper.js:37-42
Vulnerability Type: Unsafe browser security configuration
Risk Level: Medium

Complete Code Snippets

scripts/scraper.py:81-84

python
browser = p.chromium.launch(
    headless=self.headless,
    args=["--disable-blink-features=AutomationControlled", "--no-sandbox"],
)

scripts/douyin_scraper.js:37-42

javascript
this.browser = await chromium.launch({
    headless: this.headless,
    args: [
        '--disable-blink-features=AutomationControlled',
        '--no-sandbox',
        '--disable-setuid-sandbox',
    ]
});

Technical Analysis

Both scraper implementations explicitly disable Chromium's process sandbox. The sandbox is a defense-in-depth boundary intended to restrict a compromised renderer or browser subprocess. The skill then navigates this unsandboxed browser to remote Douyin pages and processes their active content.

Disabling both the standard and setuid sandboxes is not required for the scraper's declared functionality in a correctly configured, non-root environment. Although exploitation still requires a suitable browser vulnerability or another compromise of browser-executed content, removing the sandbox substantially reduces containment if such a vulnerability is triggered.

Attack Path

  1. The skill launches Chromium with --no-sandbox; the Node.js implementation also passes --disable-setuid-sandbox.
  2. The browser navigates to remotely controlled content on Douyin or content delivered through a compromised upstream page or dependency.
  3. Malicious page content exploits a vulnerability in Chromium, its renderer, or a browser component.
  4. Because the Chromium sandbox is disabled, the compromised browser process has fewer isolation barriers.
  5. The attacker executes actions under the operating-system identity of the scraper process and accesses resources available to that identity.

Impact Assessme

...[truncated 575 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove --no-sandbox and --disable-setuid-sandbox from both implementations.
  2. Run Chromium as a dedicated, unprivileged operating-system user with no access to unrelated credentials or files.
  3. Configure the host or container so Chromium's supported sandbox can initialize correctly.
  4. If sandbox disabling is unavoidable in a constrained environment, make it an explicit opt-in option and run the complete scraper inside a tightly isolated, non-root container.
  5. Apply a read-only filesystem where possible, drop Linux capabilities, enable no-new-privileges, restrict outbound networking, and expose only a dedicated output directory.
  6. Keep Chromium pinned to a supported security-patched release and establish a controlled update process.
  7. Avoid placing API keys or unrelated secrets in the browser process environment.
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill claims to scrape Douyin and extract keywords from natural language, but the finding indicates it instead depends on undeclared external search services and may return simulated example data. Undisclosed third-party retrieval and fabricated fallback results are dangerous because they can leak user queries externally and misrepresent authenticity, especially in a skill framed as direct scraping.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The skill claims to scrape Douyin and extract keywords from natural language, but the finding indicates it instead depends on undeclared external search services and may return simulated example data. Undisclosed third-party retrieval and fabricated fallback results are dangerous because they can leak user queries externally and misrepresent authenticity, especially in a skill framed as direct scraping.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The skill claims to scrape Douyin and extract keywords from natural language, but the finding indicates it instead depends on undeclared external search services and may return simulated example data. Undisclosed third-party retrieval and fabricated fallback results are dangerous because they can leak user queries externally and misrepresent authenticity, especially in a skill framed as direct scraping.

Content

No source excerpt is available for this finding.

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 · install_playwright_docker.py (reported line 30)May include surrounding context.

python
def mode_native() -> None:
    env = os.environ.copy()
    env.setdefault("PLAYWRIGHT_DOWNLOAD_HOST", "https://npmmirror.com/mirrors/playwright")
    env.setdefault("PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST", "https://cdn.npmmirror.com/binaries/chrome-for-testing")
    venv_python = Path("venv/bin/python")

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill documentation is presented entirely in Chinese from the title onward, with no indication that other languages are supported or that Chinese is required for a region-specific compliance reason. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding

The skill declares no explicit tool scope or permissions even though its documented behavior invokes shell execution, network access, and likely local file operations. Missing least-privilege boundaries makes it easier for the skill to run with broader capabilities than users or the platform may expect, increasing the blast radius if the skill is misused or modified.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are broad enough to overlap with ordinary user requests for searching content, which can cause the skill to activate unexpectedly. Because this skill performs shell and network actions, overbroad activation increases the chance of unintended external requests and command execution on benign conversation turns.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Intent-based activation without clear non-trigger conditions is unsafe for a skill that can perform scraping, web search fallback, and shell execution. Ambiguous matching can lead to accidental invocation, causing unanticipated external data access or actions inconsistent with the user's actual request.

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 and instructions do not warn users that it may perform external scraping and web-search fallback, which means user input may be transmitted to third-party services without clear notice. Lack of transparency around outbound network retrieval is a security and privacy issue, particularly when fallback to external search is marked as mandatory.

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 · install_playwright_docker.py (reported line 14)May include surrounding context.

python
def run(cmd: list[str], cwd: str | None = None, env: dict[str, str] | None = None) -> None:
    print("\n>>>", " ".join(cmd))
    subprocess.run(cmd, cwd=cwd, env=env, check=True)


def mode_official() -> None:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code file includes natural-language descriptions and CLI help text that force a specific language/locale for users. Under the policy, language restrictions should either be optional for the user or clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill claims to scrape Douyin search results, but this code fabricates example records after visiting the site instead of extracting actual page content. In an agent setting, this can mislead users and downstream automation into treating invented data as real, creating integrity and trust risks even though it is not a direct code-execution issue.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The hot-list feature is presented as retrieving real trending Douyin content, but the implementation generates synthetic trending entries. This is dangerous because consumers may act on fabricated popularity data, causing misinformation, bad business decisions, or false reporting.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The command help and console output are presented only in Chinese, which constitutes a language/locale policy issue when no choice is offered. There is no flag, environment setting, or documentation indicating that Chinese-only output is intentional and limited to a justified regional use case.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The fallback sends the user's search keyword to Brave Search without any explicit warning or consent. In the context of a search skill, user queries may contain sensitive interests or proprietary terms, so silent third-party transmission creates a meaningful privacy and data-governance issue.

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 · scripts/scraper.py (reported line 155)May include surrounding context.

python
query = f"site:douyin.com {keyword}"
            # Try using the built-in web search by calling the CLI
            proc = subprocess.run(
                ["curl", "-s", "https://api.search.brave.com/res/v1/web/search",
                 "-H", "Accept: application/json",
                 "-H", f"X-Subscription-Token: {self._get_brave_key()}",

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This code transmits query data to the Brave Search API, which is an external third party outside the expected Douyin scraping boundary. In context, that is more dangerous because users invoking a Douyin scraper may not expect their search terms to be shared with another provider at all.

Content

Scanner excerpt · scripts/scraper.py (reported line 156)May include surrounding context.

python
query = f"site:douyin.com {keyword}"
            # Try using the built-in web search by calling the CLI
            proc = subprocess.run(
                ["curl", "-s", "https://api.search.brave.com/res/v1/web/search",
                 "-H", "Accept: application/json",
                 "-H", f"X-Subscription-Token: {self._get_brave_key()}",
                 "--", f"https://api.search.brave.com/res/v1/web/search?q={urllib.parse.quote(query)}&count={min(limit, 10)}"],

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The constructed request URL includes the encoded user query and sends it to Brave Search, confirming external transmission of user-supplied search terms. This creates privacy and compliance risk, especially if users enter sensitive names, brands, or internal topics assuming a single-site Douyin lookup.

Content

Scanner excerpt · scripts/scraper.py (reported line 159)May include surrounding context.

python
["curl", "-s", "https://api.search.brave.com/res/v1/web/search",
                 "-H", "Accept: application/json",
                 "-H", f"X-Subscription-Token: {self._get_brave_key()}",
                 "--", f"https://api.search.brave.com/res/v1/web/search?q={urllib.parse.quote(query)}&count={min(limit, 10)}"],
                capture_output=True, text=True, timeout=15
            )
            if proc.returncode == 0 and proc.stdout:

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

When real retrieval fails, the script fabricates mock search and hot-list results and returns them in the same data structure as real scraped results. This is dangerous because downstream users or agents may treat invented content as authentic Douyin data, enabling misinformation, bad automation decisions, or hidden test-data contamination.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill's stated purpose is scraping Douyin data, but it silently falls back to Brave Search using an environment-sourced API key. That expands data flow to an unrelated third party and uses a sensitive credential without making this behavior clear, creating privacy and least-privilege concerns in a skill that users would reasonably expect to interact only with Douyin.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The script reads a Brave API key from the environment and uses it for external requests without any disclosure to the user or clear trust boundary explanation. While reading environment variables is common, in a skill context this can unexpectedly consume sensitive host-provided credentials and couple user actions to hidden external services.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The hot-list path also performs third-party Brave requests without warning the user that data is being sent externally. Even though the category term may seem low sensitivity, undisclosed external transmission violates user expectations for a Douyin scraper and broadens exposure of activity metadata.

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 · scripts/scraper.py (reported line 202)May include surrounding context.

python
try:
            import subprocess
            query = f"site:douyin.com 抖音热榜 {category}" if category else "site:douyin.com 抖音热榜"
            proc = subprocess.run(
                ["curl", "-s", f"https://api.search.brave.com/res/v1/web/search?q={query}&count={min(limit, 10)}",
                 "-H", "Accept: application/json",
                 "-H", f"X-Subscription-Token: {self._get_brave_key()}"],

Static analysis

No suspicious patterns detected.