Back to skill

Security audit

Baoyu Url To Markdown

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly does what it says, but it can automatically send target URLs to a third-party service and can fetch arbitrary page media without enough safeguards.

Review before installing. Avoid using this skill on private, signed, token-bearing, intranet, or authenticated URLs unless you are comfortable with a failed local capture sending the full URL to defuddle.md. Keep media handling on ask/never for untrusted pages, because media download can make your machine fetch arbitrary URLs from page content. Prefer a preinstalled trusted Bun runtime and pinned dependencies or a lockfile before running it in a sensitive environment.

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)

other

Warning
Location
scripts/main.ts:101
Finding

Automatic Disclosure of Sensitive Target URLs to a Third-Party Service

Content
View full analysis
{ const apiUrl = buildDefuddleApiUrl(targetUrl); const response = await fetch(apiUrl, { headers: { accept: "text/markdown,text/plain;q=0.9,*/*;q=0.1", }, }); if (!response.ok) { throw new Error(`defuddle.md returned ${response.status} ${response.statusText}`); } ``` The fallback is invoked automatically after local capture fails: ```ts } catch (error) { const primaryError = error instanceof Error ? error.message : String(error); console.warn(`Primary capture failed: ${primaryError}`); console.warn("Trying defuddle.md API fallback..."); try { const remoteResult = await fetchDefuddleApiMarkdown(args.url); outputPath = args.output || await generateOutputPath(args.url, remoteResult.title, args.outputDir); ``` ### Technical Analysis The Skill accepts an arbitrary user-supplied URL and, if local browser capture fails, embeds the entire URL into a request sent to the external `defuddle.md` service. The fallback does not require separate user confirmation and does not filter URL credentials, query parameters, fragments, private hostnames, or internal network addresses. URLs may contain sensitive information such as signed query parameters, password-reset tokens, session identifiers, private document identifiers, internal hostnames, or confidential search terms. Although the code does not send captured HTML or browser cookies to `defuddle.md`, sending the full URL can still disclose secrets and browsing intent to that service and its infrastructure logs. This beha ...[truncated 1159 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

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

Server-Side Request Forgery Through Unrestricted Media Downloads

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:22
Finding

Unpinned Runtime Execution and Mutable Third-Party Dependencies

Content
View full analysis
.ts` 3. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun 4. Replace all `{baseDir}` and `${BUN_X}` in this document with actual values ``` Dependencies use mutable semver ranges, and no lockfile was present in the audited directory: ```json { "name": "baoyu-url-to-markdown-scripts", "private": true, "type": "module", "dependencies": { "@mozilla/readability": "^0.6.0", "baoyu-chrome-cdp": "file:./vendor/baoyu-chrome-cdp", "defuddle": "^0.12.0", "jsdom": "^24.1.3", "linkedom": "^0.18.12", "turndown": "^7.2.2", "turndown-plugin-gfm": "^1.0.2" } } ``` ### Technical Analysis `npx -y bun` permits the package registry to select and download the current matching `bun` package without user confirmation or an exact version. The downloaded package is then executed with the privileges of the agent process. The application dependencies also use caret ranges. In the absence of an audited lockfile with integrity metadata, future installation can resolve package versions different from those reviewed during this audit. This does not prove that any listed dependency is currently malicious, but it weakens reproducibility and creates a supply-chain execution channel. The local `baoyu-chrome-cdp` dependency is vendored through a file reference and is therefore less exposed to registry substitution. The remaining registry dependencies and the unpinned `npx` runtime remain mutable. ### Attack Path 1. The host does not have a loca ...[truncated 990 chars]
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

This mismatch is more dangerous because it indicates undeclared process inspection, discovery of existing Chrome debug sessions, reuse of user data directories, and browser control. If the actual scripts do this while the skill advertises simple URL-to-markdown conversion, users may unknowingly expose authenticated browser context, local browsing data, or permit control of existing Chrome sessions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This mismatch is more dangerous because it indicates undeclared process inspection, discovery of existing Chrome debug sessions, reuse of user data directories, and browser control. If the actual scripts do this while the skill advertises simple URL-to-markdown conversion, users may unknowingly expose authenticated browser context, local browsing data, or permit control of existing Chrome sessions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This mismatch is more dangerous because it indicates undeclared process inspection, discovery of existing Chrome debug sessions, reuse of user data directories, and browser control. If the actual scripts do this while the skill advertises simple URL-to-markdown conversion, users may unknowingly expose authenticated browser context, local browsing data, or permit control of existing Chrome sessions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

This mismatch is more dangerous because it indicates undeclared process inspection, discovery of existing Chrome debug sessions, reuse of user data directories, and browser control. If the actual scripts do this while the skill advertises simple URL-to-markdown conversion, users may unknowingly expose authenticated browser context, local browsing data, or permit control of existing Chrome sessions.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `scripts/main.ts` | CLI entry point for URL fetching |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `scripts/legacy-converter.ts` | Pre-Defuddle legacy extraction and markdown conversion |

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill declares broad operational behavior involving environment inspection and network access, but it does not define an explicit tool scope such as permissions or allowed-tools. In an agent setting, this can cause the skill to run with ambient privileges the user did not intend, increasing the chance of overbroad network access or local environment disclosure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

Using npx -y bun without a pinned version allows retrieval of whatever package version is current at execution time. This creates a supply-chain risk where behavior can change unexpectedly or a compromised upstream package could be executed 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 76)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
78% confidence
Finding

The skill instructs the agent to create and persist an EXTEND.md preferences file in either the project or user home directory. Persisting behavior across sessions can have security and privacy implications if users are not clearly informed that future runs may inherit saved network, output, or media-handling preferences, especially at user-scope.

Content

Scanner excerpt · SKILL.md (reported line 76)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:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documented fallback to https://defuddle.md/<url> sends the target URL, and potentially sensitive content context, to a third-party service without a prominent privacy warning or explicit consent step. This is especially risky for private, authenticated, internal, or user-specific pages where the URL itself may contain secrets or reveal sensitive resources.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code automatically fetches every remote media URL found in markdown and writes the response bytes to local disk. That creates an SSRF-style network access surface and unannounced persistence of untrusted remote content, which can expose internal services if attacker-controlled markdown is processed and can store harmful or unexpected files locally without user awareness.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The code reads Chrome debug metadata from profile directories and falls back to process inspection via ps aux to identify remote-debugging ports. Even though this is local-only probing, it inspects existing browser state and running processes without transparency, which can reveal or enable access to active authenticated browser sessions unrelated to the requested task.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code enumerates default Chrome user-data directories, reads DevToolsActivePort files, inspects running processes, and connects to any discoverable local Chrome CDP endpoint tied to those profiles. In a URL-to-markdown skill, reusing an already-running browser session can expose authenticated tabs, cookies, and page contents far beyond the single user-requested URL, expanding access into sensitive browsing context without explicit consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

This function silently creates a profile directory and launches Chrome with remote debugging enabled, which materially changes the local system state and opens a powerful automation interface. Without clear disclosure and consent, users may not realize a browser instance is being started with a persistent profile and CDP port, creating risk of unintended data retention or local exposure to browser control.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The manifest uses a caret range for @mozilla/readability, which permits automatic installation of newer minor/patch releases instead of a single locked version. In a skill that fetches and processes arbitrary web content, this increases supply-chain and reproducibility risk because different installs may pull different code, including versions with newly introduced vulnerabilities or behavior changes.

Content

Scanner excerpt · scripts/package.json (reported line 6)May include surrounding context.

json
"private": true,
  "type": "module",
  "dependencies": {
    "@mozilla/readability": "^0.6.0",
    "baoyu-chrome-cdp": "file:./vendor/baoyu-chrome-cdp",
    "defuddle": "^0.12.0",
    "jsdom": "^24.1.3",

Unverifiable Dependency: @mozilla/readability has 1 known advisory(ies) (CVE-2025-2792 (@mozilla/readability Denial of Service through Regex)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
86% confidence
Finding

The manifest does not pin @mozilla/readability, and there is a known advisory affecting some releases, so the actual installed version cannot be verified from this file alone. In this skill, readability operates on fetched remote content, which makes even a denial-of-service issue more relevant because a malicious page could potentially trigger parser-heavy behavior and disrupt the conversion workflow.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The defuddle dependency is not pinned and uses a caret range, allowing the installed version to drift over time. This is more concerning here because defuddle is central to transforming untrusted remote HTML into markdown, so pulling an unexpected vulnerable or compromised release could directly affect processing of attacker-controlled input.

Content

Scanner excerpt · scripts/package.json (reported line 8)May include surrounding context.

json
"dependencies": {
    "@mozilla/readability": "^0.6.0",
    "baoyu-chrome-cdp": "file:./vendor/baoyu-chrome-cdp",
    "defuddle": "^0.12.0",
    "jsdom": "^24.1.3",
    "linkedom": "^0.18.12",
    "turndown": "^7.2.2",

Unverifiable Dependency: defuddle has 2 known advisory(ies) (CVE-2026-30830 (defuddle vulnerable to XSS via unescaped string interpolation in _findContentByS); CVE-2026-61824 (Defuddle vulnerable to XSS via unescaped attribute interpolation in site extract)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
95% confidence
Finding

defuddle has known advisories and the manifest does not pin an exact version, so it is impossible to determine whether installs will resolve to a vulnerable release. This is especially relevant because the skill's purpose is to fetch arbitrary URLs and transform their content; if a vulnerable defuddle version is used, attacker-controlled pages could potentially trigger XSS or unsafe output in downstream consumers of the generated markdown/HTML.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

The jsdom dependency is specified with a caret range, so consumers may install different versions over time. Because jsdom parses and models remote HTML/DOM content, version drift can expose the skill to parser bugs or security regressions without any code change in the repository.

Content

Scanner excerpt · scripts/package.json (reported line 9)May include surrounding context.

json
"@mozilla/readability": "^0.6.0",
    "baoyu-chrome-cdp": "file:./vendor/baoyu-chrome-cdp",
    "defuddle": "^0.12.0",
    "jsdom": "^24.1.3",
    "linkedom": "^0.18.12",
    "turndown": "^7.2.2",
    "turndown-plugin-gfm": "^1.0.2"

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

linkedom is unpinned, which creates nondeterministic builds and avoidable supply-chain exposure. Since the skill processes arbitrary pages and may rely on DOM emulation behavior, silent dependency updates can introduce vulnerable parsing behavior or break security assumptions.

Content

Scanner excerpt · scripts/package.json (reported line 10)May include surrounding context.

json
"baoyu-chrome-cdp": "file:./vendor/baoyu-chrome-cdp",
    "defuddle": "^0.12.0",
    "jsdom": "^24.1.3",
    "linkedom": "^0.18.12",
    "turndown": "^7.2.2",
    "turndown-plugin-gfm": "^1.0.2"
  }

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
91% confidence
Finding

turndown is allowed to float within the major version because of the caret specifier. Although markdown conversion libraries are not inherently dangerous, this skill converts attacker-controlled page content, so parser/output changes from unreviewed updates can create security or integrity issues downstream.

Content

Scanner excerpt · scripts/package.json (reported line 11)May include surrounding context.

json
"defuddle": "^0.12.0",
    "jsdom": "^24.1.3",
    "linkedom": "^0.18.12",
    "turndown": "^7.2.2",
    "turndown-plugin-gfm": "^1.0.2"
  }
}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
90% confidence
Finding

turndown-plugin-gfm is not pinned, which means dependency resolution may change over time. In a content-transformation pipeline handling arbitrary remote pages, even plugin-level drift can alter sanitization/output behavior or pull in an unexpected compromised release.

Content

Scanner excerpt · scripts/package.json (reported line 12)May include surrounding context.

json
"jsdom": "^24.1.3",
    "linkedom": "^0.18.12",
    "turndown": "^7.2.2",
    "turndown-plugin-gfm": "^1.0.2"
  }
}

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/vendor/baoyu-chrome-cdp/src/index.test.ts:89

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/vendor/baoyu-chrome-cdp/src/index.ts:220

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/vendor/baoyu-chrome-cdp/src/index.ts:97