Back to skill

Security audit

小红书视频下载器

Security checks for vulnerabilities and agentic risk

Overview

This downloader is purpose-aligned, but it should be reviewed because it defaults to using local browser login cookies and has scoping weaknesses around URLs, output paths, and runtime dependencies.

Review before installing. Use --browser none when possible, only process links you trust, avoid summarizing private or sensitive videos, and prefer a sandboxed environment because the skill can read browser session data through yt-dlp and may install transcription dependencies at runtime.

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)

T08 · Insecure Dependencies

Warning
Location
scripts/parallel_transcribe.py:2
Finding

Mutable Third-Party Dependency Installed During Runtime

Content
View full analysis
=3.10" # dependencies = [ # "faster-whisper>=1.0.0", # ] # /// ``` The dependency declaration is automatically processed through: ```python # Try uv run first, then fall back to direct python cmd_uv = ["uv", "run", transcribe_script, audio_path, "-o", output_dir] cmd_py = [sys.executable, transcribe_script, audio_path, "-o", output_dir] try: subprocess.run(cmd_uv, check=True) except (subprocess.CalledProcessError, FileNotFoundError): print("uv not available, trying direct Python execution...") ``` ### Technical Analysis The Whisper fallback executes `uv run` against a script containing inline dependency metadata. This can cause `uv` to resolve and install `faster-whisper` and its transitive dependencies at runtime. The constraint `faster-whisper>=1.0.0` is open-ended and does not provide an exact version, an upper bound, a reviewed lockfile, or artifact hashes. Consequently, the code executed during one Skill run can differ from the code reviewed during the audit. A compromised future package version, compromised transitive dependency, or compromised package index could introduce arbitrary code into the runtime environment. This is a supply-chain weakness rather than evidence that the current `faster-whisper` package is malicious. ### Attack Path 1. The user requests a full resource pack or AI summary. 2. Manual and automatically generated subtitle acquisition fail. 3. `download_subtitles()` enters the local Whisper fallback. 4. The downloader invokes `uv run scripts/parallel_transcribe.py`. 5. `uv` resolves the open-ended `faster-whisper>=1.0.0` requirement and its transitive dependencies. 6. If a resolved package or distribution artifact has be ...[truncated 634 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/download_xiaohongshu.py:88
Finding

Remote Video Title Can Escape the Intended Output Directory

Content
View full analysis
:"/\\|?*]', '', title) # Collapse whitespace sanitized = re.sub(r'\s+', ' ', sanitized).strip() # Truncate to reasonable length if len(sanitized) > 100: sanitized = sanitized[:100].rstrip() return sanitized or "untitled" ``` The resulting remote title is directly joined to the selected output root: ```python if full_mode: safe_title = sanitize_title(title) output_dir = os.path.join(output_path, safe_title) os.makedirs(output_dir, exist_ok=True) video_output = os.path.join(output_dir, "video.%(ext)s") ``` Subsequent files are then written beneath that unresolved path: ```python if summary_mode: meta_path = os.path.join(output_dir, ".meta.json") meta = { "title": title, "url": url, "duration": f"{duration // 60}:{duration % 60:02d}" if duration else "unknown", "platform": "Xiaohongshu (小红书)", "uploader": uploader, } with open(meta_path, "w", encoding="utf-8") as f: json.dump(meta, f, ensure_ascii=False, indent=2) ``` ### Technical Analysis A title equal to `..` remains `..` after `sanitize_title()`. Joining it to an output root produces a path that resolves to the parent directory. A title equal to `.` similarly resolves to the output root rather than a dedicated resource-pack directory. The implementation does not canonicalize the candidate path or verify that the resolv ...[truncated 1773 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
reference/summary-prompt.md:18
Finding

Untrusted Transcript Content Is Interpolated into AI Instructions Without Isolation

Content
View full analysis
/transcript.txt ``` 2. Read the metadata file: ``` ~/Downloads//.meta.json ``` 3. Read the summary prompt template: ``` reference/summary-prompt.md ``` 4. Replace the template placeholders with actual values: - `{{TITLE}}` — from .meta.json - `{{URL}}` — from .meta.json - `{{DURATION}}` — from .meta.json - `{{PLATFORM}}` — "Xiaohongshu (小红书)" - `{{TRANSCRIPT}}` — contents of transcript.txt 5. Generate the summary following the template structure. 6. Save the result to: ``` ~/Downloads//summary.md ``` ``` The template places the untrusted transcript inside a Markdown code fence: ```markdown ### Transcript ``` {{TRANSCRIPT}} ``` ``` ### Technical Analysis Downloaded subtitles, automatically generated subtitles, and speech transcriptions are untrusted external content. The template directly substitutes that content into an instruction-bearing prompt without explicitly stating that instructions found inside the transcript must be ignored. A crafted subtitle can contain triple backticks that terminate the intended Markdown code fence, followed by text framed as new model instructions. Even without delimiter termination, instruction-like content inside a transcript may influence the model because the prompt provides no strong trust-boundary rule. This can redirect or contaminate summary generation. It is an indirect prompt-injection issue confined to the AI summary workflow; the reviewed instructions do not direct the model to execute transcript ...[truncated 1179 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
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (27)

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · README.md (reported line 131)May include surrounding context.

scripts/download_xiaohongshu.py "URL" -o ~/Videos/

Download audio only

python scripts/download_xiaohongshu.py "URL" -a

Full resource pack

python scripts/download_xiaohongshu.py "URL" --full

Full resource pack with AI summary metadata

python scripts/download_xiaohongshu.py "URL" --summary

List available formats

python scripts/download_xiaohongshu.py "URL" --list-formats

Use Firefox cookies instead of Chrome

python scripts/download_xiaohongshu.py "URL" --browser firefox

text

## Subtitle Acquisition Strategy

The full resource pack mode uses a 3-tier strategy to obtain subtitles:

1. **Manual subtitles** — Tries to download creator-uploaded subtitles via `yt-dlp --write-subs`
2. **Auto-generated subtitles** — Tries platform auto-generated subtitles via `yt-dlp --write-auto-subs`
3. **Whisper transcription** — Falls back to local speech-to-text using [faster-whisper](https://github.com/SYSTRAN/faster-whisper)

The Whisper fallback uses intelligent silence-based audio

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The documented behavior materially differs from the analyzed implementation claims, which means users and reviewers may approve a skill under false assumptions about what it actually does. Security review depends on accurate disclosure; a behavior mismatch can conceal unexpected processing paths, data access, or execution steps.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 31)May include surrounding context.

md
/opt/homebrew/Caskroom/miniconda/base/envs/myenv/bin/python scripts/download_xiaohongshu.py "URL" --list-formats

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 41)May include surrounding context.

md
/opt/homebrew/Caskroom/miniconda/base/envs/myenv/bin/python scripts/download_xiaohongshu.py "URL" --list-formats

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 47)May include surrounding context.

md
/opt/homebrew/Caskroom/miniconda/base/envs/myenv/bin/python scripts/download_xiaohongshu.py "URL" --list-formats

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 53)May include surrounding context.

md
/opt/homebrew/Caskroom/miniconda/base/envs/myenv/bin/python scripts/download_xiaohongshu.py "URL" --list-formats

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · SKILL.md (reported line 114)May include surrounding context.

ript.txt

  1. Generate the summary following the template structure.

  2. Save the result to:

    text
    ~/Downloads/<video title>/summary.md
    

Options Reference

OptionDescriptionDefault
-o, --outputOutput directory~/Downloads
-q, --qualityVideo quality (best, 1080p, 720p, 480p)best
--browserBrowser for cookies (chrome, firefox, safari, none)chrome
-a, --audio-onlyDownload audio only as MP3false
--list-formatsList available formatsfalse
--fullFull resource pack modefalse
--summaryAI summary mode (implies --full)false

Output Structure

Basic mode (default)

text
~/Downloads/
└── <title> [<id>].mp4

Full resource pack mode (--full or --summary)

text
~/Downloads/<video title>/
├── video.mp4          # Original video
├── audio.mp3          # Extracted audio
├── subtitle.vtt       # We

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
91% confidence
Finding

The browser-cookie extraction feature matches information-stealer patterns because it reads authentication material from local browsers, and it is enabled by default via the browser option. While the apparent purpose is to access gated media rather than exfiltrate credentials, the capability is still dangerous because it handles highly sensitive session data that could be abused if the tool or its dependencies are compromised.

Content

Scanner excerpt · scripts/download_xiaohongshu.py (reported line 463)May include surrounding context.

python
help="Output directory (default: ~/Downloads)"
    )
    parser.add_argument(
        "-q", "--quality",
        default="best",
        choices=["best", "1080p", "720p", "480p"],
        help="Video quality (default: best)"
    )
    parser.add_argument(
        "--browser",
        default="chrome",
        choices=["chrome", "firefox", "safari", "none"],
        help="Browser to extract cookies from (default: chrome)"
    )
    parser.add_argument(
        "-a", "--audio-only",
        action="store_true",
        help="Download only audio as MP3"
    )
    parser.add_argument(
        "--list-formats",
        action="store_true",
        help="List available formats without downloading"
    )
    parser.add_argument(
        "--full",
        action="store_true",
        help="Full resource pack: video + audio + subtitles + transcript"
    )
    parser.add_argument(
        "--summary",
        action="store_true",
        help="Enable AI summary mode (saves metadata for Cl

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README explicitly advertises automatic browser cookie extraction for authentication, but it does not clearly warn users that this accesses browser-stored session material. In a skill context, that is security-relevant because users may not realize the tool can read authenticated browser data and use it to act as them on Xiaohongshu.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README promotes AI-generated summaries but does not clearly disclose that transcripts, subtitles, and metadata may be sent to Claude or another external model for processing. That creates a privacy and data-handling risk, especially if downloaded content contains personal, private, or copyrighted material.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · README.md (reported line 390)May include surrounding context.

md
## Star History

[![Star History Chart](https://api.star-history.com/svg?repos=smile7up/xiaohongshu-downloader&type=Date)](https://star-history.com/#smile7up/xiaohongshu-downloader&Date)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill instructs the agent to use shell commands and to read/write local files, but it declares no explicit tool scope or permissions. This weakens security boundaries and user visibility, making it easier for a skill to invoke powerful capabilities without clear consent or policy enforcement.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The workflow explicitly relies on cookie-authenticated access and browser state to download content, but the description does not clearly warn users that browser cookies or logged-in session data may be accessed. Without prominent disclosure, users may unknowingly authorize access to account-linked data, increasing privacy and consent risk.

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/download_xiaohongshu.py (reported line 21)May include surrounding context.

python
def check_yt_dlp():
    """Check if yt-dlp is installed."""
    try:
        result = subprocess.run(["yt-dlp", "--version"], capture_output=True, text=True, check=True)
        print(f"yt-dlp version: {result.stdout.strip()}")
        return True
    except (subprocess.CalledProcessError, FileNotFoundError):

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/download_xiaohongshu.py (reported line 33)May include surrounding context.

python
def check_ffmpeg():
    """Check if ffmpeg is installed."""
    try:
        subprocess.run(["ffmpeg", "-version"], capture_output=True, text=True, check=True)
        return True
    except (subprocess.CalledProcessError, FileNotFoundError):
        print("Error: ffmpeg is not installed.")

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script automatically supports --cookies-from-browser and defaults to using Chrome cookies for metadata retrieval and downloads, giving the tool access to authenticated browser session data. In a skill context, this is a high-risk capability because it broadens scope from simple downloading to harvesting local browser secrets that can authenticate as the user to third-party services.

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/download_xiaohongshu.py (reported line 61)May include surrounding context.

python
cmd.append(url)

    try:
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        return json.loads(result.stdout)
    except subprocess.CalledProcessError as e:
        stderr = e.stderr or ""

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/parallel_transcribe.py (reported line 67)May include surrounding context.

python
cmd.append(url)

    try:
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        return json.loads(result.stdout)
    except subprocess.CalledProcessError as e:
        stderr = e.stderr or ""

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/download_xiaohongshu.py (reported line 82)May include surrounding context.

python
if browser and browser != "none":
        cmd.extend(["--cookies-from-browser", browser])
    cmd.append(url)
    subprocess.run(cmd)


def sanitize_title(title):

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/download_xiaohongshu.py (reported line 117)May include surrounding context.

python
audio_path,
    ]
    try:
        subprocess.run(cmd, capture_output=True, text=True, check=True)
        print(f"Audio extracted: {audio_path}")
        return audio_path
    except subprocess.CalledProcessError as e:

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/parallel_transcribe.py (reported line 124)May include surrounding context.

python
audio_path,
    ]
    try:
        subprocess.run(cmd, capture_output=True, text=True, check=True)
        print(f"Audio extracted: {audio_path}")
        return audio_path
    except subprocess.CalledProcessError as e:

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/download_xiaohongshu.py (reported line 159)May include surrounding context.

python
cmd.extend(["--cookies-from-browser", browser])
    cmd.append(url)

    subprocess.run(cmd, capture_output=True, text=True)
    found = _find_and_rename_vtt(output_dir, "temp_sub", vtt_path)
    if found:
        print(f"Manual subtitles found: {vtt_path}")

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/download_xiaohongshu.py (reported line 180)May include surrounding context.

python
cmd.extend(["--cookies-from-browser", browser])
    cmd.append(url)

    subprocess.run(cmd, capture_output=True, text=True)
    found = _find_and_rename_vtt(output_dir, "temp_sub", vtt_path)
    if found:
        print(f"Manual subtitles found: {vtt_path}")

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/download_xiaohongshu.py (reported line 204)May include surrounding context.

python
cmd_py = [sys.executable, transcribe_script, audio_path, "-o", output_dir]

    try:
        subprocess.run(cmd_uv, check=True)
    except (subprocess.CalledProcessError, FileNotFoundError):
        print("uv not available, trying direct Python execution...")
        try:

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/download_xiaohongshu.py (reported line 208)May include surrounding context.

python
except (subprocess.CalledProcessError, FileNotFoundError):
        print("uv not available, trying direct Python execution...")
        try:
            subprocess.run(cmd_py, check=True)
        except subprocess.CalledProcessError as e:
            print(f"Whisper transcription failed: {e}")
            return None

Static analysis

No suspicious patterns detected.