Back to skill

Security audit

Chinese Ebook Downloader

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed ebook downloader, but it automates risky third-party downloads and handles passwords, archives, and document rendering without enough guardrails.

Review this skill before installing. It contacts third-party ebook and file-hosting sites, may reveal requested titles and passwords to those sites, downloads and extracts untrusted files, can overwrite or delete local outputs, and converts untrusted EPUB content with weak sandboxing. Use only with content you are authorized to access, use a unique throwaway file-host password, run it in a sandboxed environment with limited filesystem and network access, and avoid broad auto-trigger use.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/download_book.py:211
Finding

Unvalidated file-host URLs can cause credential disclosure to attacker-controlled sites

Content
View full analysis
Optional[dict]: _owns_browser = browser is None if _owns_browser: p = await async_playwright().start() browser = await p.chromium.launch(headless=headless) page = await browser.new_page() try: print(f"Decrypting file host link...") await page.goto(file_url, wait_until='domcontentloaded', timeout=30000) await asyncio.sleep(3) body_text = await (await page.query_selector('body')).inner_text() if '输入文件' in body_text or '访问密码' in body_text or '解密' in body_text: input_box = await page.query_selector( 'input[type="text"], input[type="password"], input.layui-input' ) if input_box and password: await input_box.type(password, delay=50) btn = await page.query_selector( 'button:has-text("解密"), ' 'input[type="submit"][value*="解密"], .layui-btn' ) if not btn: btn = await page.query_selector('button, input[type="submit"]') if btn: await btn.click() print(f" Entered password: {password}") await asyncio.sleep(5) ``` The secondary-source implemen ...[truncated 3802 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/epub_to_pdf.py:13
Finding

Untrusted EPUB markup is rendered without a restricted resource fetcher

Content
View full analysis
body {{ font-family: "Noto Sans CJK SC", "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 11pt; line-height: 1.8; max-width: 700px; margin: 0 auto; padding: 40px; }} h1, h2, h3 {{ font-weight: bold; margin-top: 1.5em; }} p {{ text-indent: 2em; margin: 0.5em 0; }} img {{ max-width: 100%; height: auto; }} {''.join(html_parts)} """ HTML(string=full_html).write_pdf(pdf_path) ``` ### Technical Analysis EPUB documents obtained from external archives are untrusted input. Their XHTML is concatenated directly into a new HTML document and passed to WeasyPrint without sanitization and without a restricted `url_fetcher`. WeasyPrint resolves external resources referenced by HTML and CSS while rendering. Untrusted EPUB content can therefore request absolute URLs through elements or styles such as: ```html @font-face { font-family: injected; src: url("file:///home/user/private-font-or-resource"); } ``` Depending on the resource type and renderer support, absolute `file://` references can also cause reads of resources available to the Skill process. Renderable local content may become embedded in the resulting PDF. Remote references disclose the runner's IP address and can access HTTP services visible only from the ru ...[truncated 2154 chars]
Remediation
View remediation
` sources - External stylesheets - CSS `url(...)` references - `@import` - `@font-face` sources outside the EPUB workspace - Embedded objects, iframes, and similar external-resource elements 6. Run conversion in a sandboxed subprocess with: - No network namespace access - A read-only root filesystem - Access only to the input workspace and output file - CPU, memory, file-size, and execution-time limits - A non-privileged user account 7. Correct the import explicitly: ```python import ebooklib from ebooklib import epub ``` Apply the resource-fetching restrictions before enabling the corrected conversion path. 8. Add tests using EPUB files that reference loopback, private IP ranges, link-local metadata addresses, remote CSS, and local files. The tests should confirm that conversion fails closed without issuing a request. ]]>
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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (47)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The declared description presents a broad multi-source ebook downloading skill with source prioritization, fallback logic, format conversion, and host-specific download handling. The supplied code chunk is much narrower: it batch-processes a static list of books and calls only download_book_from_annas_archive from source C. It checks for existing PDFs, validates file size, and logs when a non-PDF file would need conversion, but does not actually convert files. The missing multi-source fallback and conversion features are material because they are central to the declared purpose. While some of the described capabilities may exist elsewhere in the full skill, this specific code chunk does not accurately reflect that full declared functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents a general-purpose ebook downloader with several source integrations and advanced download/conversion capabilities. This code chunk is much narrower: it batch-processes a fixed list of titles and delegates searching/downloading to search_source_c.py only. Within the provided code, the implemented behavior is limited to trying title variants, checking for resulting PDF/EPUB files, moving them to an output directory, and basic timeout/rate limiting. Several headline capabilities in the description are absent from this chunk, especially multi-source fallback, broad format support, actual EPUB-to-PDF conversion, and the specialized host-handling logic. Because the actual code's purpose and capabilities are materially narrower and different from the declared description, this is a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a general-purpose multi-source ebook downloader with sophisticated fallback and format-conversion behavior. The supplied code chunk is much narrower: it is a batch script for a specific set of hardcoded books, and it directly calls only download_book_from_annas_archive from source C. There is no evidence here of source A or B fallback logic, multi-format workflow, conversion, or the specialized host-handling features described. While this script is related to ebook downloading, its actual behavior is a materially narrower and different subset of the declared functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The core declared purpose—downloading Chinese ebooks from online sources with file-host decryption, countdown waiting, JS/API extraction, GBK ZIP handling, and support for common ebook formats—is mostly aligned with the code. However, there are material description/behavior gaps. The description promises automatic A→B→C fallback across three sources, but this code implements only source A and a source C fallback to Anna’s Archive; no source B logic is present in this chunk. It also explicitly claims EPUB→PDF auto-conversion via weasyprint, yet the code contains no import or use of weasyprint and no conversion functionality. Additionally, while multiple formats are partly supported when extracting ZIP contents, direct downloaded files are always renamed with a .pdf extension, which does not fully match the claimed format-aware support. Because these are substantive advertised capabilities that are not implemented here, this is a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description centers on downloading Chinese-language ebooks from multiple online sources with fallback and various host-handling features, with EPUB→PDF conversion as an auxiliary capability. The provided code chunk does none of the downloading or source-management behavior. It only performs local file conversion to PDF by reading EPUB content and rendering HTML to PDF, plus batch processing of local .epub/.mobi files. This is a materially different primary purpose from the declared downloader. Additionally, the script appears inconsistent about MOBI support because it invokes epub.read_epub even for .mobi files. Therefore the description does not accurately represent the supplied code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The declared description presents a broad ebook downloader spanning multiple sources and additional processing features. The supplied code chunk is much narrower: it is specifically an Anna’s Archive search/download module. It does match some declared elements, such as Anna’s Archive use, Chinese ebook search, multiple mirror fallback, download attempts, and countdown-based slow-download handling. However, several major claimed capabilities are absent from this code: there is no A→B→C orchestration across sources, no source A or B logic, no format conversion with weasyprint, no GBK ZIP handling, and no JS API extraction/decryption workflows. Because the declared purpose significantly overstates what this specific code chunk does, the description does not accurately represent the supplied code chunk.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This flow is designed to wait out countdown gates, inspect page state, and extract external direct-download links from partner pages, effectively bypassing anti-bot and access-friction controls. That behavior materially increases abuse potential by automating access to gated third-party downloads; given the skill's piracy-oriented ebook acquisition context, this is especially concerning and not a benign downloader feature.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README describes automated downloading, ZIP extraction, and batch output, but does not clearly warn users that invoking the skill will contact external sites, download untrusted archives, extract files, and write data to disk. In a skill that automates retrieval from file-hosting services and archive extraction, missing disclosure materially increases the risk of unsafe user consent, accidental disk changes, and exposure to malicious or unexpected downloaded content.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill advertises very broad auto-trigger phrases for common book-download requests, which can cause the agent to invoke a networked, file-writing workflow without sufficiently explicit user confirmation or narrow scoping. In this context, the skill performs external searches and downloads files from multiple third-party sources, so accidental activation increases the chance of unintended network access, copyright-risky retrieval, and filesystem modification.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill advertises and documents operations requiring network, shell execution, and filesystem read/write, but it does not declare any explicit tool scope or permission boundaries. In an agent environment, this weakens least-privilege controls and can allow the skill to be invoked with broader capabilities than users or reviewers expect.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The invocation phrases are broad enough to match ordinary user requests like 'download this book' or generic ebook-format requests, which can cause the skill to trigger unexpectedly. In this context, unexpected activation is more dangerous because the skill performs network retrieval and file-writing for copyrighted content from third-party sources, increasing the chance of unauthorized or risky actions without sufficiently explicit user intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code removes files it deems 'fake' based on size alone using os.remove(f). Although there is a print statement immediately before deletion, the script-level description does not disclose that it may automatically delete files, and there is no confirmation prompt for this destructive action.

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

python
os.makedirs(tmp_dir, exist_ok=True)
        
        try:
            result = subprocess.run(
                [PYTHON, f"{SCRIPT_DIR}/search_source_c.py", title, book["author"], tmp_dir],
                capture_output=True, text=True, timeout=120
            )

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script unconditionally deletes any existing destination file before moving a newly downloaded file into place. In a downloader that fetches untrusted remote content, this can destroy a user's existing local copy and replace it with incorrect, corrupted, or maliciously crafted content without confirmation, making accidental data loss or unsafe overwrite more likely.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

This code removes downloaded files when they exist but are smaller than 1000 bytes, which is a file-deletion operation. Although the script prints success and failure messages, there is no user-facing disclosure that files may be automatically deleted as part of error handling, and the deletion behavior is not explained in comments or documentation visible in this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script automatically sends user-requested book titles/authors to multiple third-party sources and downloads content from them, but it does not provide an explicit privacy or consent warning at execution time. In this skill context, that is more concerning because the workflow intentionally queries several external ebook and file-hosting services, which can expose user interests and metadata to untrusted operators.

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

python
'--max-time', '600',
        '--connect-timeout', '30'
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    return result.returncode == 0

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_book.py (reported line 401)May include surrounding context.

python
'--max-time', '600',
        '--connect-timeout', '30'
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    return result.returncode == 0

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

python
'--max-time', '600',
        '--connect-timeout', '30'
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    return result.returncode == 0

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

python
'--max-time', '600',
        '--connect-timeout', '30'
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    return result.returncode == 0

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

python
if size < 1024:  # Too small, probably an error page
        return False
    
    result = subprocess.run(['file', filepath], capture_output=True, text=True)
    output = result.stdout.lower()
    
    # Check for valid document types

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_book.py (reported line 459)May include surrounding context.

python
if size < 1024:  # Too small, probably an error page
        return False
    
    result = subprocess.run(['file', filepath], capture_output=True, text=True)
    output = result.stdout.lower()
    
    # Check for valid document types

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The module description and example usage explicitly constrain the skill to Chinese ebooks and Chinese metadata inputs, but there is no user opt-in or documented justification for enforcing this locale. Under the policy, forcing a specific language without user choice can be a natural-language locale violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The script downloads untrusted remote content, invokes external programs, and writes extracted files to disk with minimal user-facing safety controls. In this skill context, which targets shadow-library and file-host downloads from third-party sites, the trust boundary is especially weak: users may unknowingly fetch malicious archives or overwrite files, making the side effects materially riskier than in a tightly controlled downloader.

Content

No source excerpt is available for this finding.

Tainted flow: 'cmd' from os.environ.get (line 393, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/download_book.py (reported line 401)May include surrounding context.

python
'--connect-timeout', '30',
        '--retry', '3'
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    return result.returncode == 0