Announcing Beacon: Self-improving memory for coding agents
← All skills
Skill

convert-web-app

skill:tldraw/tldraw#convert-web-app

This skill should be used when the user asks to "add MCP App support to my web app", "turn my web app into a hybrid MCP App", "make my web page work as an MCP App too", "wrap my existing UI as an MCP App", "convert iframe embed to MCP App", "turn my SPA into an MCP App", or needs to add MCP App support to an existing web application while keeping it working standalone. Provides guidance for analyzing existing web apps and creating a hybrid web + MCP App with server-side tool and resource registration.

Verdict
Suspicious

Risky behavior the analysis could not rule out.

Analyzed Oct 27, 2026, 23:06 UTC at 48c9de8

Dispute security verdict

If you believe this verdict is incorrect, submit a dispute and we'll review it.

2
findings
high
highest severity
2
threat classes
4,840
files scanned
91/91
checks satisfied
0
package advisories

Why this verdict

  • suspicious: finding skill:apps/mcp-app/.claude/skills/convert-web-app:apps/mcp-app/.claude/skills/convert-web-app/SKILL.md:26:SUPPLY
  • suspicious: finding skill:apps/mcp-app/.claude/skills/convert-web-app:apps/mcp-app/.claude/skills/convert-web-app/SKILL.md:538:EXEC

Security findings 2

Code execution

highContextual risklow confidence

The skill instructs the agent to install and run the basic-host example from the externally cloned repository to test the converted app, executing remotely fetched code on the host.

SERVERS='[
vector:instruction
Counter-argument considered

The strongest case against this finding is that running the official SDK's basic-host example is a standard, openly documented testing step and the npm install pulls from the official registry, invoking the pinned official-registry carve-out; but the code executed is fetched by git clone at a runtime-resolved version, not a pinned registry install, and the artifact does not pin those dependencies. Execution from the cloned repo is a concrete source-to-sink chain, and no declared claim (D1/D2 example assets, D8 SERVERS URLs) declares running code fetched from github.com, so the finding stands.

Supply chain

mediumContextual risklow confidence

The skill instructs the agent to clone the official MCP SDK repository from GitHub at a version branch resolved at runtime into /tmp and then read and adapt its source files and examples as guidance, so the instructions the agent follows depend on remote content fetched at execution time.

git clone --branch 
vector:instruction
Counter-argument considered

The strongest case against this finding is that the clone targets the official modelcontextprotocol org and the version comes from the official npm registry, invoking the pinned official-registry carve-out; but the reference is resolved at runtime rather than pinned to an immutable version, and the skill then directs the agent to read and adapt the cloned sources as guidance, so the carve-out does not neutralize it. The behavior is in the skill body, is a remote-content-to-agent-instructions chain, and the request's own residue analysis flags network 'github.com' as undeclared (declared claims D1/D2 cover only example apps' external assets, D8 only SERVERS URLs), so the low-confidence contextual_risk finding stands.

Coverage gaps 27

Parts of the artifact the static analysis could not fully examine.

context:unanalyzable_binary binary content is only byte-scanned
apps/docs/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
apps/docs/public/images/starter-kit-images/agent-starter.avif
context:unanalyzable_binary binary content is only byte-scanned
apps/docs/public/images/starter-kit-images/branching-chat-starter.avif
context:unanalyzable_binary binary content is only byte-scanned
apps/docs/public/images/starter-kit-images/chat-starter.avif
context:unanalyzable_binary binary content is only byte-scanned
apps/docs/public/images/starter-kit-images/multiplayer-starter.avif
context:unanalyzable_binary binary content is only byte-scanned
apps/docs/public/images/starter-kit-images/shader-starter.avif
context:unanalyzable_binary binary content is only byte-scanned
apps/docs/public/images/starter-kit-images/workflow-starter.avif
context:unanalyzable_binary binary content is only byte-scanned
apps/dotcom/client/public/favicon.ico
context:inventory_path_collision duplicate real/virtual path; first content retained
apps/dotcom/sync-worker/src/utils/tarStreamReader-fixtures/multi-file.tar!/records/doc1.json
context:inventory_path_collision duplicate real/virtual path; first content retained
apps/dotcom/sync-worker/src/utils/tarStreamReader-fixtures/with-prefix.tar!/path/to/file.json
context:unanalyzable_binary binary content is only byte-scanned
apps/examples/public/bonk.webm
context:unanalyzable_binary binary content is only byte-scanned
apps/examples/public/fluid.mp4
context:unanalyzable_binary pdf content is only byte-scanned
apps/examples/src/examples/use-cases/exam-marking/assets/biologyExamExample.pdf
context:unanalyzable_binary pdf content is only byte-scanned
apps/examples/src/examples/use-cases/pdf-editor/assets/tldraw.pdf
context:unanalyzable_binary binary content is only byte-scanned
templates/agent/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
templates/branching-chat/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
templates/chat/src/app/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
templates/nextjs/src/app/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
templates/shader/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
templates/sync-cloudflare/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
templates/vite/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
templates/vue/public/favicon.ico
context:unanalyzable_binary binary content is only byte-scanned
templates/workflow/public/favicon.ico
context:manifest_unparseable toml: Invalid value (at line 27, column 8)
apps/dotcom/zero-cache/flyio-replication-manager.template.toml
context:manifest_unparseable toml: Invalid value (at line 12, column 24)
apps/dotcom/zero-cache/flyio-view-syncer.template.toml
context:manifest_unparseable yaml: YAML aliases are not permitted
internal/grafana/resources/dashboards.v2.dashboard.grafana.app/mcp-server.yaml
context:manifest_unparseable yaml: YAML input exceeds 1048576 bytes
pnpm-lock.yaml