Back to skill

Security audit

douyin-keyword-search

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to scrape Douyin as described, but it also changes the local environment and can save screenshots of logged-in pages without enough disclosure.

Review before installing. Use an isolated Python environment and preferably a dedicated Douyin test account/browser session. Be aware that dependency setup can download code and browser binaries, and delete debug_screenshot.png if it is created after a failed scrape.

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
douyin_keyword_search.py:44
Finding

Unpinned and Unverified Runtime Dependency Installation

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1; douyin_keyword_search.py:44-50
Vulnerability Type: Supply-chain exposure through mutable dependencies and runtime installation
Risk Level: Medium

Vulnerable Code

requirements.txt:1

text
playwright>=1.40.0

douyin_keyword_search.py:44-50

python
def install_dependencies():
    """安装依赖"""
    print("正在安装 Playwright...")
    os.system(f'"{sys.executable}" -m pip install playwright')
    os.system(f'"{sys.executable}" -m playwright install chromium')
    print("依赖安装完成,请重新运行脚本")
    sys.exit(0)

Technical Analysis

The dependency specification permits any Playwright release equal to or newer than version 1.40.0. The fallback installation routine is even less constrained, installing playwright without specifying a version. It then downloads and installs a Chromium browser build at runtime.

No lock file, package hash, browser revision verification, or trusted artifact policy is present. Consequently, the effective code and browser binaries executed by the Skill can change after the Skill itself has been reviewed.

The package name is legitimate, and the reviewed code does not specify an obviously malicious repository. This finding concerns supply-chain integrity rather than evidence that the current Playwright package is malicious.

Attack Path

  1. A user follows the installation instructions or runs the Skill without Playwright installed.
  2. The Skill offers to invoke pip install playwright.
  3. The package manager resolves the latest package satisfying the mutable dependency constraint.
  4. Playwright subsequently downloads a compatible Chromium build.
  5. If the package index, resolved release, distribution channel, account, or downloaded browser artifact is compromised, attacker-controlled code can execute during installation or later browser startup.
  6. That code runs under the same operating-system account and privileges as the user invoking the Skil ...[truncated 485 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin Playwright to an explicitly reviewed version, for example playwright==<audited-version>.
  2. Generate a lock file containing cryptographic hashes and install with hash verification, such as pip install --require-hashes.
  3. Pin and document the corresponding Playwright browser revision.
  4. Obtain Python packages and browser artifacts only from approved, authenticated repositories.
  5. Verify downloaded artifact checksums or signatures before installation.
  6. Remove automatic dependency installation from normal runtime behavior. Fail safely and direct users to a separate, reviewable setup procedure.
  7. Check return codes for every installation command and abort on failure.
  8. Run installation and browser automation in a least-privileged virtual environment or isolated container.

T09 · Insecure Skill Coding Practices

Note
Location
douyin_keyword_search.py:160
Finding

Automatic Screenshot May Persist Sensitive Authenticated Page Data

Content
View full analysis

Vulnerability Details

File Location: douyin_keyword_search.py:160-168
Vulnerability Type: Unannounced persistence of potentially sensitive browser content
Risk Level: Low

Vulnerable Code

python
            if not items:
                # 尝试获取页面内容用于调试
                print("警告:未能找到视频卡片,尝试获取页面信息...")
                content = page.content()
                print(f"页面内容长度: {len(content)}")

                # 截图保存用于调试
                screenshot_path = os.path.join(os.path.dirname(__file__), 'debug_screenshot.png')
                page.screenshot(path=screenshot_path)
                print(f"已保存截图到: {screenshot_path}")

Technical Analysis

The workflow can ask the user to log in to Douyin manually. If none of the expected result-card selectors match, the program automatically captures the current browser viewport and writes it to the predictable path debug_screenshot.png inside the project directory.

The capture is not opt-in, and the documentation does not disclose its creation, retention, permissions, or cleanup behavior. An authenticated page screenshot can contain a search query, account identity, recommendations, notifications, or other information visible in the browser.

The file is not transmitted externally by the reviewed code. Exposure requires another party or process to obtain access to the local artifact, such as through project sharing, source-control inclusion, backups, or permissive local filesystem access.

Attack Path

  1. The user starts the Skill in non-headless mode and logs in to Douyin.
  2. Douyin changes its markup, returns an unexpected page, or otherwise causes all configured item selectors to fail.
  3. The failure branch automatically captures the current authenticated browser viewport.
  4. The screenshot is saved under the fixed filename debug_screenshot.png in the Skill directory.
  5. The directory is subsequently committed, archived, backed up, shared, or read by another local user or process.
  6. I ...[truncated 503 chars]
Remediation
View remediation

Remediation Suggestions

  1. Disable diagnostic screenshots by default and require an explicit command-line option such as --debug-screenshot.
  2. Prompt for informed consent before capturing an authenticated browser page.
  3. Clearly document what can be captured, where it is stored, and how long it is retained.
  4. Store diagnostic images in a permission-restricted temporary directory rather than the project directory.
  5. Generate unpredictable filenames and create files with owner-only permissions.
  6. Redact account identifiers, search terms, notifications, and other sensitive regions before saving.
  7. Automatically delete diagnostic artifacts after troubleshooting or at process exit.
  8. Add diagnostic files to .gitignore as defense in depth, while not relying on source-control exclusions as the primary protection.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (8)

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
95% confidence
Finding

The script executes shell commands to install Python packages at runtime, which modifies the local environment and implicitly trusts package indexes and the current interpreter configuration. Even though the command string is not directly user-controlled here, invoking a shell from a scraping utility expands the attack surface and can lead to unintended code execution through compromised package sources, interpreter hijacking, or unsafe operational use.

Content

Scanner excerpt · douyin_keyword_search.py (reported line 41)May include surrounding context.

python
def install_dependencies():
    """安装依赖"""
    print("正在安装 Playwright...")
    os.system(f'"{sys.executable}" -m pip install playwright')
    os.system(f'"{sys.executable}" -m playwright install chromium')
    print("依赖安装完成,请重新运行脚本")
    sys.exit(0)

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
95% confidence
Finding

This line invokes a shell command to download and install browser binaries at runtime, causing unreviewed system changes outside the stated scraping function. Runtime installation is risky in an agent/skill context because it performs external code and binary retrieval, which can be abused if the environment, package source, or execution path is untrusted.

Content

Scanner excerpt · douyin_keyword_search.py (reported line 42)May include surrounding context.

python
"""安装依赖"""
    print("正在安装 Playwright...")
    os.system(f'"{sys.executable}" -m pip install playwright')
    os.system(f'"{sys.executable}" -m playwright install chromium')
    print("依赖安装完成,请重新运行脚本")
    sys.exit(0)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

All user-facing descriptions and prompts in the file are written in Chinese, including the CLI description and runtime interaction text. Under the stated policy, forcing a specific language without offering user choice is a locale/language policy issue unless clearly justified as region-specific with opt-in or documentation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file's purpose is Douyin searching/scraping, but it also contains an automatic environment-modification capability unrelated to core scraping logic. In a skill setting this is more dangerous because users may expect read-only data collection behavior, not package and binary installation that changes the host and pulls code from the network.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script performs package and browser installation through shell commands without an upfront safety notice that it will alter the local system and fetch external components. Lack of explicit warning undermines informed consent and makes this behavior especially risky in an agent skill, where execution may be delegated or automated.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill explicitly encourages browser automation against Douyin and notes that login may be required, but it does not warn users that the automation may run inside their authenticated browser context and access account-linked content or session-scoped data. In an agent-skill setting, that omission can lead users to grant the skill broader access than they realize, increasing privacy and account-risk exposure.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The dependency is specified with a lower bound only, which allows future unreviewed Playwright releases to be installed. This weakens reproducibility and can introduce breaking changes or supply-chain risk if a compromised or vulnerable upstream version is later resolved during installation.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
playwright>=1.40.0

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file's natural-language instructions, parameter explanations, and warnings are all presented only in Chinese. Under the language/locale policy category, forcing a specific language without user opt-in or documented justification is a policy concern.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.