Back to skill

Security audit

Baoyu Danger X To Markdown

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed X-to-Markdown converter, but it handles live X session cookies and media downloads in ways that deserve careful review before installation.

Install only if you are comfortable letting the skill use X session cookies. Prefer a dedicated X account or dedicated Chrome profile, avoid storing cookies in shared or synced folders, rotate/revoke X sessions after use, and avoid --download-media for untrusted content until URL allowlisting, download limits, and safer cookie storage are added.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/media-localizer.ts:212
Finding

Blind SSRF Through Unrestricted Media Localization

Content
View full analysis
(); const fmMatch = markdown.match(/^---\n([\s\S]*?)\n---/); if (fmMatch) { const coverMatch = fmMatch[1]?.match(FRONTMATTER_COVER_RE); if (coverMatch?.[2] && !seen.has(coverMatch[2])) { seen.add(coverMatch[2]); candidates.push({ url: coverMatch[2], hint: "image" }); } } MARKDOWN_LINK_RE.lastIndex = 0; let match: RegExpExecArray | null; while ((match = MARKDOWN_LINK_RE.exec(markdown))) { const label = match[1] ?? ""; const rawUrl = match[3] ?? ""; if (!rawUrl || seen.has(rawUrl)) continue; const isImage = label.startsWith("!["); if (!isImage && !isPlausibleMediaUrl(rawUrl)) continue; seen.add(rawUrl); candidates.push({ url: rawUrl, hint: isImage ? "image" : "unknown", }); } return candidates; } ``` ```ts for (const candidate of candidates) { try { const downloadUrl = toHighResUrl(candidate.url); const response = await fetch(downloadUrl, { method: "GET", redirect: "follow", headers: { "user-agent": DOWNLOAD_USER_AGENT, }, }); ``` ### Technical Analysis Media URLs are extracted from generated or previously saved Markdown and passed to `fetch` without validating their destination. Image syntax is sufficient to make any HTTP or HTTPS URL a download candidate. The implementation does not: - Restrict requests to expected X media hosts. - Reject loopback, private, link-local, multicast, or reserved IP ranges. - Resolve and validate DNS results. - Validate the destination of each redirect. - Disable cross-origin redirects. - Require HT ...[truncated 1629 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/media-localizer.ts:287
Finding

Unbounded Remote Media Downloads Can Exhaust Memory and Disk

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/cookie-file.ts:66
Finding

X Session Cookies Are Persisted Without Explicit Restrictive Permissions

Content
View full analysis
{ const dir = path.dirname(p); await mkdir(dir, { recursive: true }); const payload: CookieFileData = { version: 1, updatedAt: new Date().toISOString(), cookieMap: cookies, source, }; await writeFile(p, JSON.stringify(payload, null, 2), "utf8"); } ``` ### Technical Analysis The cookie map contains X authentication material, including `auth_token` and `ct0`. It is serialized to a plaintext JSON file. Neither the containing directory nor the file is created with explicit restrictive permissions. The resulting access controls depend on the process umask and any permissions already present on the file. If the file already exists with permissive permissions, overwriting it does not correct those permissions. The path can also be overridden through environment variables, increasing the likelihood of storage in an inappropriate location. ### Attack Path 1. The user logs in to X through the Chrome CDP workflow. 2. The Skill captures the authenticated X cookies. 3. `write_cookie_file` writes the complete cookie map to `cookies.json`. 4. The file receives permissions derived from the ambient umask or retains existing permissive permissions. 5. Another local account, shared process, backup system, or synchronization service reads the file. 6. The exposed session token is reused to access the user's X account within the token's validity and X's session controls. ### Impact Assessment Exposure of `auth_token` can provide access equivalent to an authenticated X browser session. The exact actions available depend on X's server-side controls, session validity, and addi ...[truncated 358 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/cookies.ts:249
Finding

Authentication Token Prefixes Are Exposed in Logs

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/paths.ts:35
Finding

Shell Injection Risk in WSL Home-Path Conversion

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:34
Finding

Mutable Bun Runtime Is Automatically Downloaded and Executed Through npx

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (33)

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding

A second independently reported description-behavior mismatch points to the same core issue: the skill's stated purpose does not fully describe what the code may actually do. Misrepresentation of capability is dangerous in agent systems because users may authorize execution based on incomplete or inaccurate expectations.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

A second independently reported description-behavior mismatch points to the same core issue: the skill's stated purpose does not fully describe what the code may actually do. Misrepresentation of capability is dangerous in agent systems because users may authorize execution based on incomplete or inaccurate expectations.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code launches or attaches to Chrome via the DevTools Protocol and programmatically extracts cookies for x.com/twitter.com using Network.getCookies. This is a credential-harvesting capability, not merely a markdown conversion feature, and it can access live authenticated browser sessions from an existing profile, which materially increases the risk of account compromise and stealthy session theft.

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
99% confidence
Finding

The YARA hit is supported by substantive behavior in the code: it waits for an authenticated X session in Chrome and extracts cookies from the browser. That combination matches information-stealer tradecraft because it targets session credentials rather than implementing a narrow content-conversion function.

Content

Scanner excerpt · scripts/cookies.ts (reported line 95)May include surrounding context.

ts
Url, 15_000);

    const page = await openPageSession({
      cdp,
      reusing,
      url: X_LOGIN_URL,
      matchTarget: (target) => target.type === "page" && (
        target.url.includes("x.com") || target.url.includes("twitter.com")
      ),
      enableNetwork: true,
    });
    const { sessionId } = page;
    targetId = page.targetId;

    if (verbose) {
      log?.(reusing
        ? `[x-cookies] Reusing existing Chrome on port ${port}. Waiting for cookies...`
        : "[x-cookies] Chrome opened. If needed, complete X login in the window. Waiting for cookies...");
    }

    const start = Date.now();
    let last: Record<string, string> = {};

    while (Date.now() - start < timeoutMs) {
      const { cookies } = await cdp.send<{ cookies: CookieLike[] }>(
        "Network.getCookies",
        { urls: ["https://x.com/", "https://twitter.com/"] },
        { sessionId, timeoutMs: 10_000 }
      );

      const m = buildXCookieMap((cookies ?? []).filter(Boolean));
      last = m;

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

High
Category
YARA Match
Confidence
84% confidence
Finding

The code explicitly loads X authentication cookies and instructs the user to provide X_AUTH_TOKEN and X_CT0 or log in via Chrome, which matches credential/session-token collection behavior. In the context of a skill whose main purpose is content conversion, handling reusable auth cookies is particularly sensitive because compromise of those tokens could allow account access and abuse beyond the tool's stated purpose.

Content

Scanner excerpt · scripts/main.ts (reported line 490)May include surrounding context.

ts
tringify(payload, null, 2), "utf8");
  log(`[x-to-markdown] Consent saved to: ${consentPath}`);
}

async function convertArticleToMarkdown(
  inputUrl: string,
  articleId: string,
  log: (message: string) => void
): Promise<string> {
  log("[x-to-markdown] Loading cookies...");
  const cookieMap = await loadXCookies(log);
  if (!hasRequiredXCookies(cookieMap)) {
    throw new Error("Missing auth cookies. Provide X_AUTH_TOKEN and X_CT0 or log in via Chrome.");
  }

  log(`[x-to-markdown] Fetching article ${articleId}...`);
  const article = await fetchXArticle(articleId, cookieMap, false);
  const referencedTweets = await resolveReferencedTweetsFromArticle(article, cookieMap, { log });
  const { markdown: body, coverUrl } = formatArticleMarkdown(article, { referencedTweets });

  const title = typeof (article as any)?.title === "string" ? String((article as any).title).trim() : "";
  const meta = formatMetaMarkdown({
    url: `https://x.com/i/article/${articleId}`,
    requestedUrl: in

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

High
Category
YARA Match
Confidence
90% confidence
Finding

The skill explicitly loads X authentication cookies and tells the user to provide X_AUTH_TOKEN and X_CT0 or log in via Chrome, indicating access to highly sensitive session credentials. In the context of a reverse-engineered API and browser cookie loading, this is dangerous because compromise of the skill or its dependencies could expose reusable session tokens and enable account hijacking or unauthorized data access.

Content

Scanner excerpt · scripts/tweet-to-markdown.ts (reported line 117)May include surrounding context.

ts
normalizeInputUrl(inputUrl);
  const tweetId = parseTweetId(normalizedUrl);
  if (!tweetId) {
    throw new Error("Invalid tweet url. Example: https://x.com/<user>/status/<tweet_id>");
  }

  const log = options.log ?? (() => {});
  log("[tweet-to-markdown] Loading cookies...");
  const cookieMap = await loadXCookies(log);
  if (!hasRequiredXCookies(cookieMap)) {
    throw new Error("Missing auth cookies. Provide X_AUTH_TOKEN and X_CT0 or log in via Chrome.");
  }

  log(`[tweet-to-markdown] Fetching thread for ${tweetId}...`);
  const thread = await fetchTweetThread(tweetId, cookieMap);
  if (!thread) {
    throw new Error("Failed to fetch thread.");
  }

  const tweets = thread.tweets ?? [];
  if (tweets.length === 0) {
    throw new Error("No tweets found in thread.");
  }

  const firstTweet = tweets[0] as any;
  const user = thread.user ?? firstTweet?.core?.user_results?.result?.legacy;
  const username = user?.screen_name;
  const name = user?.name;
  const author =
    username

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises capabilities that require environment and network access, but it does not declare an explicit tool/permission scope. That makes the trust boundary unclear and can lead an agent runtime to grant broader capabilities than users expect, especially since the skill also reads local files and may invoke networked tooling.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding

Using npx -y bun without pinning a version introduces a supply-chain risk: execution behavior depends on whatever package/version is resolved at runtime. An attacker controlling or compromising the upstream package, dependency path, or registry response could cause arbitrary code execution in the user's environment.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
### First-Time Setup (BLOCKING)

**CRITICAL**: When EXTEND.md is not found, you **MUST use `AskUserQuestion`** to ask the user for their preferences before creating EXTEND.md. **NEVER** create EXTEND.md with defaults without asking. This is a **BLOCKING** operation — do NOT proceed with any conversion until setup is complete.

Use `AskUserQuestion` with ALL questions in ONE call:

Session Persistence

Medium
Category
Rogue Agent
Confidence
84% confidence
Finding

The skill instructs creation of persistent preference files and also stores consent state on disk. Persisting session-like state is not inherently malicious, but it can create privacy and security concerns if sensitive choices, account-related metadata, or paths are stored unprotected, especially on shared systems.

Content

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

md
### First-Time Setup (BLOCKING)

**CRITICAL**: When EXTEND.md is not found, you **MUST use `AskUserQuestion`** to ask the user for their preferences before creating EXTEND.md. **NEVER** create EXTEND.md with defaults without asking. This is a **BLOCKING** operation — do NOT proceed with any conversion until setup is complete.

Use `AskUserQuestion` with ALL questions in ONE call:

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill resolves a local Chrome profile directory and defines cookie names required for X authentication, indicating capability to access browser-stored session data. Accessing local browser profiles for auth cookies is highly sensitive because it can enable reuse of a user's logged-in session without a standard OAuth flow, potentially exposing account access and private data. This is more dangerous in context because the skill is framed as a content-conversion utility, yet it contains machinery for local session extraction tied to a reverse-engineered API.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file hardcodes a default X/Twitter bearer token and related authentication-oriented constants. Even if the bearer token is a commonly reused public web client token rather than a secret tied to the developer, embedding auth material in a skill that also handles user cookies lowers the barrier to making authenticated requests against X and normalizes use of reverse-engineered access paths. In this skill context, that is more dangerous because the manifest explicitly mentions user consent and browser-session use, so these constants are part of a workflow that can leverage a user's authenticated state.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code persists X/Twitter authentication cookies to disk without any built-in user-facing disclosure, confirmation, or protection controls. Because these cookies can represent active authenticated session state for a reverse-engineered API, storing them silently increases the risk of unintended credential retention, local compromise, or later misuse by other code on the system.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code accepts X authentication cookies from environment variables and turns them into active session material for later requests. While this may be intended as a convenience feature, it broadens the skill from simple content conversion into handling bearer-like authentication secrets, increasing the chance of credential misuse, accidental disclosure, or reuse outside the user's expectations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

Sensitive authentication cookies are sourced from environment variables without any user-facing disclosure in this file about the risks of supplying session secrets. This can cause users or operators to expose long-lived account credentials to the skill in ways they may not realize are equivalent to handing over account access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code persists harvested X cookies to disk, creating a local cache of active session credentials. Storing session cookies at rest increases exposure to other local processes, backups, accidental sharing, or later compromise, especially if file permissions and encryption are not strictly controlled.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This TypeScript code issues HTTP requests to X endpoints using headers built from cookies, a user agent, and a bearer token. The file contains no confirmation prompt, print/log disclosure, or comments/docstrings warning that user/session data and credentials will be sent over the network.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The function reads X_USER_AGENT and X_BEARER_TOKEN from environment variables and then uses them for outbound API access. In this file there is no accompanying comment, docstring, prompt, or log message informing the user that sensitive environment-based credentials are being consumed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This exported function performs another authenticated network call using request headers derived from cookieMap and bearerToken. The code does not provide any in-file warning, confirmation, or user-visible notice that account/session-linked data is transmitted externally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The article entity request also sends headers built from cookies and bearer token to a remote service. There are no comments, docstrings, prompts, or logs in this file warning that sensitive session/authentication material is included in outbound requests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code hard-codes both "x-twitter-client-language" and "accept-language" to "en", which imposes a specific language/locale in outgoing requests. This matches the policy category for language or locale constraints because there is no user opt-in, configuration path, or documented region-specific justification in this file.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill performs browser-based login/cookie refresh in addition to content conversion, expanding its privileges from simple URL processing into authenticated session handling. That increases exposure to credential/session-token misuse and makes the skill more dangerous in context because it uses a reverse-engineered X workflow and handles authentication material unrelated to markdown formatting itself.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The function emits the string "引用推文" directly when rendering tweet quote blocks, which imposes Chinese output regardless of the user's language or locale preference. This is a natural-language policy concern because the file provides no mechanism for language selection, opt-in, or documented region-specific justification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code automatically fetches attacker-controlled URLs parsed from markdown and writes the responses to local disk, with no confirmation, allowlist, or explicit trust boundary. In the context of a conversion skill that processes X/Twitter content, this creates SSRF-style network access to arbitrary hosts referenced in markdown and can persist untrusted files locally, increasing risk of internal network probing, unexpected data transfer, and storage of dangerous content.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/paths.ts:39

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/graphql.ts:256