Back to skill

Security audit

Fetch & Archive to Lexiang

Security checks for vulnerabilities and agentic risk

Overview

This skill performs the promised archival workflow, but it also reuses browser sessions, extracts cookies, reads local tokens, and uploads content using external credentials in ways that deserve careful review.

Install only if you intentionally want an agent to reuse logged-in browser sessions, access browser cookies, read Lexiang-related local credentials, and upload archived content/media to Lexiang. Use a dedicated browser profile and least-privilege Lexiang credentials, avoid running it on unrelated private sessions, and review logs because token material may be partially printed.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (22)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
start_script = Path.home() / ".fetch_article" / "start-cdp-chrome.sh"
    if start_script.exists():
        print(f"🚀 调用 {start_script} 启动 CDP Chrome...")
        subprocess.run(["bash", str(start_script)], check=False)
    else:
        if not _launch_cdp_chrome_via_open(port):
            return False
Confidence
91% confidence
Finding
The script executes a user-home script at ~/.fetch_article/start-cdp-chrome.sh if present, with no integrity validation or trust boundary checks. Any local process or prior compromise that can place or alter that file gains code execution when this skill runs, which is especially dangerous because the script is used to access authenticated browser state.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# On macOS, cookies are encrypted. We need to decrypt them.
        # Get the Chrome Safe Storage key from Keychain
        try:
            result = subprocess.run(
                [
                    "security",
                    "find-generic-password",
Confidence
99% confidence
Finding
This code invokes macOS security to retrieve the Chrome Safe Storage secret, then uses it to decrypt browser cookies. That is credential access beyond normal archival needs and enables theft or replay of authenticated web sessions across sites.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill declares powerful behaviors including shell execution, network access, file reads/writes, and use of local environment state, but it does not declare permissions or explicitly scope those capabilities. That weakens reviewability and consent, making it easier for the skill to access sensitive local data or perform remote actions without clear operator awareness.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill’s stated purpose sounds like content fetching and archival, but the instructions also direct reuse of a live Chrome profile/login state via CDP, interaction with remote Lexiang APIs, and direct media uploads. In context, this materially expands the trust boundary: it can leverage authenticated sessions and credentials to bypass access controls or act on external services in ways a user may not reasonably infer from the description.

Description-Behavior Mismatch

High
Confidence
100% confidence
Finding
The file explicitly states that it fetches paywalled content by extracting Chrome cookies, reusing real-browser login state, and bypassing anti-automation and Cloudflare protections. In the context of an archival skill, this is dangerous because it repurposes a user's authenticated session to access protected content without a legitimate, minimal-scope auth flow.

Context-Inappropriate Capability

High
Confidence
100% confidence
Finding
The code copies Chrome's Cookies database, queries domain cookies, retrieves the Keychain secret, derives the decryption key, and reconstructs usable cookie values. This is a classic session-hijacking capability and can expose account access for any supported domain, far exceeding the stated archival purpose.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
This block launches or connects to a real Chrome profile specifically to reuse full login state and defeat anti-automation controls. That creates a high-risk bridge from the skill into the user's authenticated browsing environment, enabling access to protected resources and increasing exposure of session data.

Intent-Code Divergence

Medium
Confidence
86% confidence
Finding
The documentation says cookie injection is the default, but the CLI actually defaults to CDP mode that reuses the user's real Chrome session. This mismatch can mislead users about the sensitivity of the operation and undermine informed consent for browser-session access.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The script reads a bearer token directly from the user's global ~/.cursor/mcp.json file outside the skill workspace, giving the skill implicit access to long-lived credentials without explicit per-run consent. In the context of an archival/fetch skill that makes outbound API calls and downloads content, this is dangerous because any modification or reuse of the script could exfiltrate or abuse the token to access the user's Lexiang data.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The script reads browser cookies by default via --cookies-from-browser chrome, which grants the downloader access to authenticated session data without an explicit opt-in at runtime. In an archival skill, defaulting to local browser credential material expands access beyond public content and can expose private or account-scoped data if misused.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The test suite hard-codes a different skill name and dependency set than the provided skill metadata, which can mask supply-chain or packaging drift and cause the repository to validate against the wrong contract. In a skill that orchestrates fetching and archival across multiple scripts, this mismatch can let unauthorized behavior or unintended dependencies pass review because the tests no longer verify the actual published identity.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The README explicitly instructs users to upload Markdown pages and media to Lexiang using personal credentials and an OpenAPI config, but it does not clearly warn that local content, metadata, and media files will be transmitted to external services. In a skill that processes arbitrary web content, videos, podcasts, and PDFs, this omission can cause users to unknowingly exfiltrate sensitive or proprietary material to third-party systems.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The guidance explicitly instructs reuse of a real logged-in Chrome session via CDP to fetch paywalled or login-gated content, but it does not include safety controls around account consent, session scope, data minimization, or protection of authenticated state. In an agent skill, this creates a meaningful risk of unauthorized access, accidental over-collection from the user's private session, and leakage of sensitive authenticated data if the browser context is reused too broadly.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The code prepares to sync cookies from the real Chrome profile into the CDP profile without a clear disclosure or per-action consent at the point of access. Because those cookies represent authenticated session material, silent reuse materially increases the chance of unauthorized access or user surprise.

Missing User Warnings

High
Confidence
99% confidence
Finding
This section reads Chrome cookies and attempts to decrypt them via Keychain access without a clear, immediate disclosure to the user. Hidden credential access is especially dangerous in a skill because users may expect article fetching, not extraction of browser secrets.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The script prints the access token to stdout, which can expose a live bearer credential in terminal history, CI logs, shell transcripts, or centralized logging systems. Because bearer tokens are sufficient for authenticated API access during their validity window, anyone who obtains the token may be able to perform actions against the Lexiang API as the configured application/user.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script accesses browser cookies without an upfront, prominent warning or affirmative consent, even though this touches sensitive local credential material. That creates a privacy and trust boundary violation, especially in an agent skill where users may not expect local browser data access for ordinary YouTube archival.

MCP Config Access

High
Category
Agent Snooping
Content
def load_token():
    """从 ~/.cursor/mcp.json 读取乐享 MCP token(去掉 Bearer 前缀)。"""
    p = os.path.expanduser("~/.cursor/mcp.json")
    d = json.load(open(p))
    auth = d["mcpServers"]["lexiang"]["headers"]["Authorization"]
Confidence
98% confidence
Finding
Accessing ~/.cursor/mcp.json to extract the Lexiang Authorization header is a direct credential-harvesting pattern. Even if intended for convenience, it bypasses normal secret isolation boundaries and allows the skill to use sensitive MCP credentials that may authorize broad API access to internal knowledge base content.

Credential Access

High
Category
Privilege Escalation
Content
def get_chrome_cookies_for_domain(domain: str) -> list[dict]:
    """Extract cookies for a domain from Chrome's cookie database.
    
    On macOS, Chrome encrypts cookies with the Keychain.
    We use a simpler approach: copy the Cookies db and read what we can,
    or use the `security` command to decrypt.
    """
Confidence
100% confidence
Finding
The function is explicitly designed to extract cookies from Chrome's database, which are authentication credentials for many web services. In a fetching/archival skill, this capability is unjustified and enables direct session hijacking or account misuse.

Credential Access

High
Category
Privilege Escalation
Content
return []

        # On macOS, cookies are encrypted. We need to decrypt them.
        # Get the Chrome Safe Storage key from Keychain
        try:
            result = subprocess.run(
                [
Confidence
100% confidence
Finding
This section specifically targets Keychain-backed Chrome cookie protection and attempts to obtain the decryption secret. Accessing and using platform credential material to unlock browser sessions is highly sensitive and characteristic of credential theft tooling.

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

High
Category
YARA Match
Content
Automatically detects and waits for Cloudflare JS challenges.

2. **Cookie injection mode** (default):
   Reads cookies from Chrome's cookie database and injects them into a fresh
   Playwright browser context. Works for most sites but Google login pages
   and Cloudflare-protected sites may detect the automation and block it.
Confidence
98% confidence
Finding
The YARA match is substantiated by the code's actual behavior: reading Chrome cookies, copying browser data, decrypting cookie values, and reusing them to access sites. In skill context, these are not incidental strings but operational capabilities aligned with information-stealer patterns.

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

High
Category
YARA Match
Content
print("📋 获取视频信息...")
    cmd = ["yt-dlp", "--dump-json", "--no-download"]
    if cookies_from_browser:
        cmd.extend(["--cookies-from-browser", cookies_from_browser])
    cmd.append(url)
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
Confidence
89% confidence
Finding
The YARA hit is not evidence of credential theft malware, but it does reflect a real sensitive capability: the script defaults to extracting browser cookies for yt-dlp. In an agent skill, automatic access to browser-stored session data materially increases risk because it can enable authenticated scraping of private or subscription-gated content without clear user intent.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
tests/test_contracts.py:17