Back to skill

Security audit

meme-digger

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly aligned with meme research, but it asks users to store full browser session cookies and includes report/downloader code with local file disclosure and unsafe content-handling risks.

Install only if you are comfortable giving the skill Bilibili/Tieba session cookies. Prefer environment variables over repo-local files, do not pass cookies on the command line, restrict config/cookies.json permissions, delete or rotate cookies after use, and review generated Markdown/HTML before sharing reports because local files or active content could be embedded.

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 (5)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/common.py:39
Finding

Session cookies are persisted without restrictive file permissions

Content
View full analysis
dict: """Write config/cookies.json while preserving entries that were not modified.""" os.makedirs(CONFIG_DIR, exist_ok=True) d = {} if os.path.exists(CONFIG_FILE): try: with open(CONFIG_FILE, encoding="utf-8") as f: d = json.load(f) except Exception: d = {} d.setdefault("bilibili", {"cookie": ""}) d.setdefault("tieba", {"cookie": ""}) if bili is not None: d["bilibili"]["cookie"] = bili.strip() if tieba is not None: d["tieba"]["cookie"] = tieba.strip() with open(CONFIG_FILE, "w", encoding="utf-8") as f: json.dump(d, f, ensure_ascii=False, indent=2) return d ``` The configuration utility also supports passing complete cookies through process arguments: ```python if args[i] == "--bili-cookie" and i + 1 < len(args): bili, i = args[i + 1], i + 1 elif args[i] == "--tieba-cookie" and i + 1 < len(args): tieba, i = args[i + 1], i + 1 ``` ### Technical Analysis Bilibili and Tieba cookies are account session credentials. The application writes them to `config/cookies.json` using a normal `open(..., "w")` operation without explicitly setting the file mode to owner-only access. For a newly created file, effective permissions depend on the process umask. In environments with a permissive umask, the file may be readable by other local users or processes. Existing insecure permissions are also not corrected. The documented command-line cookie options create a second exposure channel. Command-line arguments may be retained in shell history and can be visible through process-inspection ...[truncated 1268 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/make_report.py:33
Finding

Report generation allows arbitrary local file embedding through image paths

Content
View full analysis
str: """Convert a local image to a base64 data URI; preserve remote image URLs.""" if src.startswith(("http://", "https://", "//")): if src.startswith("//"): return "https:" + src return src p = src if os.path.isabs(src) else os.path.join(base_dir, src) if not os.path.exists(p): return "" ext = os.path.splitext(p)[1].lower().lstrip(".") mime = {"jpg": "image/jpeg", "jpeg": "image/jpeg", "png": "image/png", "gif": "image/gif", "webp": "image/webp"}.get(ext, "image/jpeg") try: with open(p, "rb") as f: b64 = base64.b64encode(f.read()).decode() return f"data:{mime};base64,{b64}" except Exception: return "" ``` Markdown image references are passed directly to this function: ```python m = re.match(r"^!\[([^\]]*)\]\(([^)]+)\)\s*(.*)$", line) if m: alt, src, cap = m.group(1), m.group(2), m.group(3).strip() data = inline_image(src, base_dir) ``` ### Technical Analysis The renderer accepts both absolute local paths and relative paths containing `../`. It joins relative paths to the working directory but does not canonicalize the result or verify that it remains inside the expected research or image directory. Consequently, any readable file can be opened and base64-encoded into the generated HTML. The implementation does not verify that the target is a regular file, reject symbolic links, inspect image signatures, or impose a size limit. A non-image file is labeled as `image/jpeg` by default, but its original bytes remain embedded and can be extracted from the HTML. The immediate input is a report Markdown file. Exploitation therefore requires an attacker to influence that file, a generated research ...[truncated 1234 chars]
Remediation
View remediation
/images`. 2. Canonicalize both the approved root and candidate path with `os.path.realpath()`. 3. Verify containment using `os.path.commonpath()` rather than string-prefix comparisons. 4. Reject: - Absolute input paths. - Paths escaping the approved root. - Symbolic links. - Non-regular files. 5. Validate file signatures with a strict allowlist for JPEG, PNG, GIF, and WebP instead of trusting filename extensions. 6. Apply a maximum source-file size before reading and base64 encoding. 7. Open files defensively where supported, including `O_NOFOLLOW`, to reduce symbolic-link race exposure. 8. Treat report Markdown as untrusted input unless it was generated and reviewed entirely within the controlled workflow. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/make_report.py:57
Finding

Unsafe Markdown rendering permits active-content injection in generated HTML

Content
View full analysis
str: """Inline formatting: bold, links, and code.""" s = html_mod.escape(s) s = re.sub(r"\*\*(.+?)\*\*", r"\1", s) s = re.sub(r"`([^`]+)`", r"\1", s) s = re.sub(r"\[([^\]]+)\]\(([^)]+)\)", lambda m: f'{m.group(1)}', s) return s ``` Heading text is kept unescaped: ```python m = re.match(r"^(#{1,4})\s+(.*)$", line) if m: level = len(m.group(1)) title = m.group(2) if level >= 2: in_gallery = ("梗图" in title) anchor = re.sub(r"[^\w\u4e00-\u9fff]+", "-", title).strip("-") icon = next((v for k, v in EMOJI.items() if k in title), "") blocks.append(("h", (level, f"{icon} {title}", anchor))) continue ``` Remote image URLs are placed directly in an HTML attribute: ```python m = re.match(r"^!\[([^\]]*)\]\(([^)]+)\)\s*(.*)$", line) if m: alt, src, cap = m.group(1), m.group(2), m.group(3).strip() data = inline_image(src, base_dir) if data: img = (f'' f'{html_mod.escape(alt)}' + (f"{inline_text(cap)}" if cap else "") + "") blocks.append(("img", img)) ``` Unescaped heading data is subsequently emitted: ```python if t == "h": level, htitle, anchor = d if level == 1: continue tag = f"h{level}" if level == 2: toc_items.append(f'
  • {htitle}
  • ') body.a ...[truncated 2245 chars]
    Remediation
    View remediation

    T09 · Insecure Skill Coding Practices

    Error
    Location
    scripts/bili_dl.py:25
    Finding

    Image downloaders allow unrestricted resource access and unbounded response reads

    Content
    View full analysis
    str | None: try: req = urllib.request.Request(url, headers={ "User-Agent": UA, "Referer": "https://www.bilibili.com/"}) with urllib.request.urlopen(req, timeout=20) as r: data = r.read() except Exception as e: print(f"!! Download failed {url[:60]}... : {e}") return None if len(data) < 1024: return None h = hashlib.md5(data).hexdigest()[:12] if h in seen: return None seen.add(h) ext = os.path.splitext(urllib.parse.urlparse(url).path)[1] or ".jpg" if ext.lower() not in (".jpg", ".jpeg", ".png", ".gif", ".webp"): ext = ".jpg" name = f"{h}{ext}" with open(os.path.join(outdir, name), "wb") as f: f.write(data) return name ``` The gallery downloader has the same unbounded read pattern: ```python def dl(url: str, referer: str = "", retries: int = 2, timeout: int = 20) -> bytes | None: hdrs = {"User-Agent": common.UA, "Accept-Language": "zh-CN,zh;q=0.9"} if referer: hdrs["Referer"] = referer last = None for _ in range(retries + 1): try: req = urllib.request.Request(url, headers=hdrs) with urllib.request.urlopen(req, timeout=timeout) as r: return r.read() except Exception as e: last = e time.sleep(1.0) return None ``` ### Technical Analysis `bili_dl.py` is explicitly designed to accept arbitrary URLs from command-line arguments or a list file. It does not enf ...[truncated 2377 chars]
    Remediation
    View remediation

    T09 · Insecure Skill Coding Practices

    Warning
    Location
    scripts/bili_memes.py:162
    Finding

    Predictable temporary URL file can overwrite and delete an existing path

    Content
    View full analysis
    0 and (t1 or t2): top = (t1 + t2)[:dl_n] print(f"\nDownloading the first {len(top)} images to {out}/ ...") import subprocess tmp = out + ".urls.txt" os.makedirs(os.path.dirname(tmp) or ".", exist_ok=True) with open(tmp, "w", encoding="utf-8") as f: f.write("\n".join(c["url"] for c in top)) subprocess.run([sys.executable, os.path.join(os.path.dirname(os.path.abspath(__file__)), "bili_dl.py"), "--from", tmp, "--out", out]) os.remove(tmp) ``` ### Technical Analysis The temporary filename is deterministically derived from the user-controlled output path. The file is opened with mode `"w"`, which truncates an existing file. After the child process returns, the path is unconditionally removed. In a shared or attacker-writable directory, another local user can predict the path and pre-create a file or symbolic link. Depending on operating-system protections and directory permissions, opening the path may overwrite the linked target. The later `os.remove(tmp)` also deletes an existing path with the same name. The subprocess invocation itself uses an argument array and does not introduce shell-command injection. The weakness is confined to temporary-file creation and cleanup. ### Attack Path 1. The victim runs `bili_memes.py` with downloads enabled and an output path predictable to another local user. 2. The attacker pre-creates `.urls.txt` as: - A valuable regular file that will be truncated, or - A symbolic link to another file writable by the victim. 3. The script opens the predictable path with `"w"`. 4. Existing content or the symbolic-link target is overwritten with image URLs. 5. After the downloader finishes, the script removes the predictable tempor ...[truncated 551 chars]
    Remediation
    View remediation
    Vulnerability Patterns
    • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
    • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
    • Behavioral ASTexec() Call, eval() Call, Dynamic Import
    • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
    • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
    Findings (42)

    Tp4

    High
    Category
    MCP Tool Poisoning
    Confidence
    97% confidence
    Finding

    The skill explicitly instructs users to copy full browser session cookies and store them in a local config file for Bilibili and Tieba, but that sensitive credential handling is insufficiently surfaced as a security-sensitive capability. Session cookies can grant account access equivalent to a logged-in browser, so collecting and persisting them creates real risk of account takeover or leakage if the workspace, logs, or generated files are exposed.

    Content

    No source excerpt is available for this finding.

    Tp4

    High
    Category
    MCP Tool Poisoning
    Confidence
    97% confidence
    Finding

    The skill explicitly instructs users to copy full browser session cookies and store them in a local config file for Bilibili and Tieba, but that sensitive credential handling is insufficiently surfaced as a security-sensitive capability. Session cookies can grant account access equivalent to a logged-in browser, so collecting and persisting them creates real risk of account takeover or leakage if the workspace, logs, or generated files are exposed.

    Content

    No source excerpt is available for this finding.

    Tp4

    High
    Category
    MCP Tool Poisoning
    Confidence
    97% confidence
    Finding

    The skill explicitly instructs users to copy full browser session cookies and store them in a local config file for Bilibili and Tieba, but that sensitive credential handling is insufficiently surfaced as a security-sensitive capability. Session cookies can grant account access equivalent to a logged-in browser, so collecting and persisting them creates real risk of account takeover or leakage if the workspace, logs, or generated files are exposed.

    Content

    No source excerpt is available for this finding.

    Tp4

    High
    Category
    MCP Tool Poisoning
    Confidence
    98% confidence
    Finding

    The skill explicitly instructs users to copy full browser session cookies and store them in a local config file for Bilibili and Tieba, but that sensitive credential handling is insufficiently surfaced as a security-sensitive capability. Session cookies can grant account access equivalent to a logged-in browser, so collecting and persisting them creates real risk of account takeover or leakage if the workspace, logs, or generated files are exposed.

    Content

    No source excerpt is available for this finding.

    Tp4

    High
    Category
    MCP Tool Poisoning
    Confidence
    98% confidence
    Finding

    The skill explicitly instructs users to copy full browser session cookies and store them in a local config file for Bilibili and Tieba, but that sensitive credential handling is insufficiently surfaced as a security-sensitive capability. Session cookies can grant account access equivalent to a logged-in browser, so collecting and persisting them creates real risk of account takeover or leakage if the workspace, logs, or generated files are exposed.

    Content

    No source excerpt is available for this finding.

    Tp4

    High
    Category
    MCP Tool Poisoning
    Confidence
    96% confidence
    Finding

    The skill explicitly instructs users to copy full browser session cookies and store them in a local config file for Bilibili and Tieba, but that sensitive credential handling is insufficiently surfaced as a security-sensitive capability. Session cookies can grant account access equivalent to a logged-in browser, so collecting and persisting them creates real risk of account takeover or leakage if the workspace, logs, or generated files are exposed.

    Content

    No source excerpt is available for this finding.

    Tp4

    High
    Category
    MCP Tool Poisoning
    Confidence
    98% confidence
    Finding

    The skill explicitly instructs users to copy full browser session cookies and store them in a local config file for Bilibili and Tieba, but that sensitive credential handling is insufficiently surfaced as a security-sensitive capability. Session cookies can grant account access equivalent to a logged-in browser, so collecting and persisting them creates real risk of account takeover or leakage if the workspace, logs, or generated files are exposed.

    Content

    No source excerpt is available for this finding.

    Tp4

    High
    Category
    MCP Tool Poisoning
    Confidence
    96% confidence
    Finding

    The skill explicitly instructs users to copy full browser session cookies and store them in a local config file for Bilibili and Tieba, but that sensitive credential handling is insufficiently surfaced as a security-sensitive capability. Session cookies can grant account access equivalent to a logged-in browser, so collecting and persisting them creates real risk of account takeover or leakage if the workspace, logs, or generated files are exposed.

    Content

    No source excerpt is available for this finding.

    Missing User Warnings

    High
    Category
    Not specified by scanner
    Confidence
    98% confidence
    Finding

    The skill asks users to extract raw Bilibili and Tieba cookies from browser developer tools and place them into a local JSON config, but it lacks a strong security warning about the sensitivity of those session credentials. Raw session cookies can be reused to impersonate the user, so encouraging this practice without secure storage guidance materially increases credential theft and account compromise risk.

    Content

    No source excerpt is available for this finding.

    Vague Triggers

    Medium
    Category
    Not specified by scanner
    Confidence
    93% confidence
    Finding

    The activation guidance is broad enough to match ordinary user requests such as asking what a meme means or where it came from, which can cause the skill to trigger in routine conversation without clear user intent to invoke this specific workflow. Because this skill performs multi-step external collection from Bilibili and Tieba, over-triggering increases unnecessary data access, expands exposure to untrusted content, and may cause the agent to act beyond what the user expected.

    Content

    No source excerpt is available for this finding.

    Undeclared Tool Scope

    Medium
    Category
    MCP Least Privilege
    Confidence
    94% confidence
    Finding

    The skill declares broad operational behavior involving shell execution, network access, filesystem reads/writes, and environment-based path resolution, but does not define any explicit tool scope or allowed-tools boundary. In an agent setting, this can cause over-privileged execution and make it easier for the skill to perform unintended network collection or local file modifications beyond what a user expects.

    Content

    No source excerpt is available for this finding.

    Vague Triggers

    Medium
    Category
    Not specified by scanner
    Confidence
    92% confidence
    Finding

    The activation trigger is broad everyday phrasing that can invoke a skill with network access, file writes, image downloading, and optional credential use in situations where the user may have intended only a simple explanation. Over-broad triggering raises the chance of unnecessary scraping, local data collection, and use of more powerful tools than warranted by the prompt.

    Content

    No source excerpt is available for this finding.

    Missing User Warnings

    Medium
    Category
    Not specified by scanner
    Confidence
    91% confidence
    Finding

    The skill instructs the agent to collect comment content, image URLs, downloaded images, manifests, and research artifacts into local files, but it does not provide a clear up-front warning to users that third-party content will be stored persistently. This creates privacy, compliance, and expectation risks, particularly because comment media may include personal data, offensive content, or copyrighted material.

    Content

    No source excerpt is available for this finding.

    Missing User Warnings

    Medium
    Category
    Not specified by scanner
    Confidence
    94% confidence
    Finding

    The script automatically loads Bilibili cookies and sends them with comment API requests, but this file provides no user-facing notice or consent prompt. Even though the destination is the legitimate Bilibili API, silently transmitting authenticated session data increases privacy and account-risk exposure if users assume the tool operates anonymously or without credentials.

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

    python
    os.makedirs(os.path.dirname(tmp) or ".", exist_ok=True)
            with open(tmp, "w", encoding="utf-8") as f:
                f.write("\n".join(c["url"] for c in top))
            subprocess.run([sys.executable, os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                                         "bili_dl.py"), "--from", tmp, "--out", out])
            os.remove(tmp)
    

    External Transmission

    Medium
    Category
    Data Exfiltration
    Confidence
    60% 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 · scripts/bili_comments.py (reported line 66)May include surrounding context.

    python
    print("用法: python bili_video.py <bvid> [--cover]")
            sys.exit(1)
        bvid = args[0].strip()
        url = f"https://api.bilibili.com/x/web-interface/view?bvid={bvid}"
        req = urllib.request.Request(url, headers={
            "User-Agent": UA, "Referer": "https://www.bilibili.com/"})
        try:
    

    External Transmission

    Medium
    Category
    Data Exfiltration
    Confidence
    60% 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 · scripts/bili_comments.py (reported line 71)May include surrounding context.

    python
    print("用法: python bili_video.py <bvid> [--cover]")
            sys.exit(1)
        bvid = args[0].strip()
        url = f"https://api.bilibili.com/x/web-interface/view?bvid={bvid}"
        req = urllib.request.Request(url, headers={
            "User-Agent": UA, "Referer": "https://www.bilibili.com/"})
        try:
    

    External Transmission

    Medium
    Category
    Data Exfiltration
    Confidence
    60% 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 · scripts/bili_comments.py (reported line 111)May include surrounding context.

    python
    print("用法: python bili_video.py <bvid> [--cover]")
            sys.exit(1)
        bvid = args[0].strip()
        url = f"https://api.bilibili.com/x/web-interface/view?bvid={bvid}"
        req = urllib.request.Request(url, headers={
            "User-Agent": UA, "Referer": "https://www.bilibili.com/"})
        try:
    

    External Transmission

    Medium
    Category
    Data Exfiltration
    Confidence
    60% 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 · scripts/bili_memes.py (reported line 53)May include surrounding context.

    python
    print("用法: python bili_video.py <bvid> [--cover]")
            sys.exit(1)
        bvid = args[0].strip()
        url = f"https://api.bilibili.com/x/web-interface/view?bvid={bvid}"
        req = urllib.request.Request(url, headers={
            "User-Agent": UA, "Referer": "https://www.bilibili.com/"})
        try:
    

    External Transmission

    Medium
    Category
    Data Exfiltration
    Confidence
    60% 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 · scripts/bili_memes.py (reported line 69)May include surrounding context.

    python
    print("用法: python bili_video.py <bvid> [--cover]")
            sys.exit(1)
        bvid = args[0].strip()
        url = f"https://api.bilibili.com/x/web-interface/view?bvid={bvid}"
        req = urllib.request.Request(url, headers={
            "User-Agent": UA, "Referer": "https://www.bilibili.com/"})
        try:
    

    External Transmission

    Medium
    Category
    Data Exfiltration
    Confidence
    60% 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 · scripts/bili_video.py (reported line 31)May include surrounding context.

    python
    print("用法: python bili_video.py <bvid> [--cover]")
            sys.exit(1)
        bvid = args[0].strip()
        url = f"https://api.bilibili.com/x/web-interface/view?bvid={bvid}"
        req = urllib.request.Request(url, headers={
            "User-Agent": UA, "Referer": "https://www.bilibili.com/"})
        try:
    

    External Transmission

    Medium
    Category
    Data Exfiltration
    Confidence
    60% 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 · scripts/config_cookies.py (reported line 36)May include surrounding context.

    python
    print("用法: python bili_video.py <bvid> [--cover]")
            sys.exit(1)
        bvid = args[0].strip()
        url = f"https://api.bilibili.com/x/web-interface/view?bvid={bvid}"
        req = urllib.request.Request(url, headers={
            "User-Agent": UA, "Referer": "https://www.bilibili.com/"})
        try:
    

    Natural-Language Policy Violations

    Medium
    Category
    Not specified by scanner
    Confidence
    96% confidence
    Finding

    The request headers force Accept-Language: zh-CN,zh;q=0.9, which imposes a specific locale on network interactions. The file does not offer a language choice or explain this locale restriction as a documented, justified regional constraint.

    Content

    No source excerpt is available for this finding.

    Natural-Language Policy Violations

    Medium
    Category
    Not specified by scanner
    Confidence
    95% confidence
    Finding

    This request explicitly sets Accept-Language to Chinese for Tieba access. Because the script does not provide a user-selectable locale or a clearly documented justification for forcing Chinese, it violates the language/locale policy criterion.

    Content

    No source excerpt is available for this finding.

    Natural-Language Policy Violations

    Medium
    Category
    Not specified by scanner
    Confidence
    95% confidence
    Finding

    The post-fetch request again forces a Chinese locale through Accept-Language: zh-CN,zh;q=0.9. Repeating the fixed locale without opt-in reinforces the policy issue across multiple request paths.

    Content

    No source excerpt is available for this finding.

    Static analysis

    No suspicious patterns detected.