Back to skill

Security audit

Web Fetcher

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real web/video downloader, but it can fetch arbitrary URLs and reuse browser login cookies without strong warnings or scope limits.

Review before installing. Use it only with URLs you trust, avoid --cookies-browser unless you understand it can use your logged-in browser sessions, run it in an isolated environment or dedicated browser profile, and constrain output directories and network access where possible.

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
lib/router.py:36
Finding

Unrestricted URL Fetching Enables Server-Side Request Forgery

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
lib/article.py:262
Finding

Unbounded Remote Resource Processing Can Exhaust Memory and Disk

Content
View full analysis
{ try { const resp = await fetch(url, {credentials: 'include'}); const blob = await resp.blob(); return new Promise((resolve) => { const reader = new FileReader(); reader.onloadend = () => resolve(reader.result); reader.readAsDataURL(blob); }); } catch(e) { return null; } } """, img_url) ``` `lib/feishu.py:162-171`: ```python match = re.match(r'data:image/(\w+);base64,(.+)', b64_data) if match: ext = match.group(1) if ext == "jpeg": ext = "jpg" img_data = base64.b64decode(match.group(2)) local_name = f"img_{i:02d}.{ext}" local_path = os.path.join(img_dir, local_name) with open(local_path, "wb") as f: f.write(img_data) ``` ### Technical Analysis The generic image downloader calls `resp.read()` without a byte limit. The entire ...[truncated 1894 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:25
Finding

Unpinned Third-Party Dependencies and Browser Assets Create Supply-Chain Risk

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (21)

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 70)May include surrounding context.

--quality N Video quality: 1080, 720, 480 (default: 1080) --method METHOD Force method: scrapling, camoufox, ytdlp, feishu --selector CSS Force CSS selector for content extraction --urls-file FILE File with URLs (one per line, # for comments) --audio-only Extract audio only (video downloads) --no-images Skip image download (articles) --cookies-browser NAME Browser for cookies (e.g., chrome, firefox)

text

## How It Works

URL → router.py (domain matching) → handler ├── article.py (scrapling GET → browser → camoufox) ├── feishu.py (virtual scroll + authenticated image fetch) └── video.py (yt-dlp wrapper)

text

Articles are converted to Markdown with images downloaded locally. Videos are downloaded as MP4 (or MP3 with `--audio-only`).

## Dependencies

Install only what you need:

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description presents the skill as a web fetcher/downloader for articles and videos across multiple services. However, the supplied code chunk is the Mozilla/Arc90-style Readability parser: it accepts an HTMLDocument object and extracts readable article content and metadata from that document. Its functions focus on DOM cleanup, content scoring, metadata extraction, image/lazy-load handling, and preserving embedded video elements when cleaning content. There is no code for HTTP requests, URL fetching, authentication, platform integration, saving content, or media/video downloading. Therefore the code’s actual behavior is a content-extraction helper, not a web-fetching/downloading skill as declared.

Content

No source excerpt is available for this finding.

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 70)May include surrounding context.

--quality N Video quality, e.g. 1080, 720 (default: 1080) --method METHOD Force method: scrapling, camoufox, ytdlp, feishu --selector CSS Force CSS selector for content extraction --urls-file FILE File with URLs (one per line, # for comments) --audio-only Extract audio only (video downloads) --no-images Skip image download (articles) --cookies-browser NAME Browser for cookies (e.g., chrome, firefox)

text

## Platform Notes

### WeChat (mp.weixin.qq.com)
- Images use `data-src` attribute with `mmbiz.qpic.cn` URLs
- Visible `<img>` tags contain SVG placeholders (lazy loading)
- Image download requires `Referer: https://mp.weixin.qq.com/` header
- Scrapling GET usually works; no browser needed

### Feishu (*.feishu.cn)
- Uses virtual scroll — content blocks are rendered on-demand
- The fetcher scrolls through the entire document, collecting `[data-block-id]` elements
- Images require authenticated fetch (cookies), downloaded v

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

python
lp", "feishu"], help="Force method")
    parser.add_argument("--selector", help="Force CSS selector")
    parser.add_argument("--urls-file", help="File with URLs (one per line)")
    parser.add_argument("--audio-only", action="store_true", help="Extract audio only (video)")
    parser.add_argument("--no-images", action="store_true", help="Skip image download (article)")
    parser.add_argument("--cookies-browser", help="Browser for cookies (e.g., chrome, firefox)")
    args = parser.parse_args()

    urls = []
    if args.urls_file:
        with open(args.urls_file) as f:
            urls = [line.strip() for line in f if line.strip() and not line.startswith("#")]
    elif args.url:
        urls = [args.url]
    else:
        parser.print_help()
        sys.exit(1)

    os.makedirs(args.output, exist_ok=True)

    results = []
    for url in urls:
        r = route(url)
        if args.method:
            r["method"] = args.method
        if args.selector:
            r["selector"] = ar

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · lib/readability.js (reported line 486)May include surrounding context.

js
titleHadHierarchicalSeparators = / [\\\/>»] /.test(curTitle);
      curTitle = origTitle.replace(/(.*)[\|\-\\\/>»] .*/gi, "$1");

      // If the resulting title is too short (3 words or fewer), remove
      // the first part instead:
      if (wordCount(curTitle) < 3)
        curTitle = origTitle.replace(/[^\|\-\\\/>»]*[\|\-\\\/>»](.*)/gi, "$1");

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

High
Category
YARA Match
Confidence
83% confidence
Finding

The cookies-browser chrome pattern matches information-stealer behavior because it directs tooling to read authenticated cookies from the user's Chrome profile. In this skill context, that is especially sensitive: the agent is a web/video fetcher, so leveraging local browser credentials can enable access to private or premium content and normalize credential-adjacent data access beyond the expected scope.

Content

Scanner excerpt · references/platforms.md (reported line 71)May include surrounding context.

md
- **Selector:** `.WB_text`
- **Method:** camoufox (recommended for reliable access)
- **Notes:** Some content requires login

## Bilibili (bilibili.com / b23.tv)

- **Method:** yt-dlp
- **Format selection:** `bestvideo[height<=N]+bestaudio/best[height<=N]`
- **Output:** Merged to MP4 via ffmpeg
- **Short links:** b23.tv redirects are handled by yt-dlp automatically
- **Premium content:** Use `--cookies-browser chrome` to pass login cookies
- **Audio extraction:** Use `--audio-only` flag for MP3 output

## YouTube (youtube.com / youtu.be)

- **Method:** yt-dlp
- **Notes:** Standard yt-dlp usage, no special handling

## Douyin (douyin.com)

- **Method:** yt-dlp
- **Notes:** May need cookies for some content

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The README explicitly documents authenticated fetching and browser-cookie use, including Feishu authenticated image access, but does not warn users that the tool may access logged-in session data and private content. In a web-fetching skill, this increases the risk of unintentionally pulling sensitive account data or normalized developer acceptance of session-backed scraping without consent boundaries.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
## Adding New Platforms

1. Add entry to `ROUTE_TABLE` in `lib/router.py`
2. If needed, add image post-processing hook in `lib/article.py`
3. If needed, create dedicated handler in `lib/`

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill advertises and documents capabilities that require network, filesystem, and shell access, but the manifest does not declare any explicit tool scope or permission boundaries. This increases the chance of overbroad execution in an agent environment and makes it harder for users or reviewers to understand what the skill is allowed to do.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrases are broad enough to match many ordinary user requests, which can cause the skill to activate in contexts where users did not intend web fetching or downloading. In an agent system with network and file-write capability, over-triggering can lead to unnecessary external requests, data collection, or local file creation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill explicitly documents use of authenticated browser cookies to access and download content, but it does not present a clear warning about privacy, account scope, or the sensitivity of browser-derived session data. This is dangerous because users may unknowingly authorize access to private or account-restricted content, and cookie-backed requests can expose personal data or violate least-privilege expectations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The --cookies-browser option enables the tool to read authentication cookies from a local browser profile, but the interface gives no explicit warning that sensitive browser-stored session data will be accessed and then potentially used against arbitrary user-supplied URLs. In a web-fetching skill, this materially increases the risk of unintended authenticated requests, privacy exposure, or misuse of a logged-in session if users do not understand what the flag does.

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

python
cmd_html += ["-s", selector]

        print(f"[*] Scrapling GET: {url}")
        r1 = subprocess.run(cmd_md, capture_output=True, text=True, timeout=60)
        r2 = subprocess.run(cmd_html, capture_output=True, text=True, timeout=60)

        md_text = _read_if_exists(md_file)

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
79% confidence
Finding

The manifest describes fetching and saving web articles/videos, which justifies network access and file writes. However, this implementation invokes external binaries via subprocess and uses a headless/anti-detection browser stack, adding execution capabilities that are not explicitly part of the stated purpose and are broader than ordinary fetching logic.

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 · lib/article.py (reported line 83)May include surrounding context.

python
print(f"[*] Scrapling GET: {url}")
        r1 = subprocess.run(cmd_md, capture_output=True, text=True, timeout=60)
        r2 = subprocess.run(cmd_html, capture_output=True, text=True, timeout=60)

        md_text = _read_if_exists(md_file)
        html_text = _read_if_exists(html_file)

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 · lib/article.py (reported line 109)May include surrounding context.

python
cmd_html += ["-s", selector]

        print(f"[*] Scrapling fetch (browser): {url}")
        r1 = subprocess.run(cmd_md, capture_output=True, text=True, timeout=120)
        r2 = subprocess.run(cmd_html, capture_output=True, text=True, timeout=120)

        md_text = _read_if_exists(md_file)

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 · lib/article.py (reported line 110)May include surrounding context.

python
print(f"[*] Scrapling fetch (browser): {url}")
        r1 = subprocess.run(cmd_md, capture_output=True, text=True, timeout=120)
        r2 = subprocess.run(cmd_html, capture_output=True, text=True, timeout=120)

        md_text = _read_if_exists(md_file)
        html_text = _read_if_exists(html_file)

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · lib/router.py (reported line 67)May include surrounding context.

python
return False

    try:
        __import__(name)
        return True
    except ImportError:
        hint = hints.get(name, f"pip install {name}")

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 · lib/video.py (reported line 36)May include surrounding context.

python
print(f"[*] Downloading: {url}")
    print(f"[*] Command: {' '.join(cmd)}")

    result = subprocess.run(cmd, capture_output=True, text=True)

    if result.returncode != 0:
        print(f"[!] yt-dlp error:\n{result.stderr}")

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documentation explicitly instructs use of --cookies-browser chrome to reuse a local browser's authenticated Bilibili session for premium content. That expands the skill from ordinary public-content fetching into accessing account-scoped or paid content via local credentials, creating risk of unauthorized access and unintended exposure of sensitive browser session data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill retrieves arbitrary remote content, follows through multiple network-fetch mechanisms including a browser engine, downloads images, and writes results to local storage with only status prints. In an agent setting, this can surprise users, enable unintended access to internal or sensitive URLs, and cause filesystem changes without clear consent or policy checks, making the context more dangerous than a standalone CLI utility.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
lib/article.py:178