Back to skill

Security audit

Playwright MCP

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent Playwright browser automation skill, but it creates reusable commands that execute a mutable remote package and can reuse saved browser login state.

Review before installing. Prefer an exact pinned @playwright/mcp version or a locally installed reviewed binary, avoid reusable links that keep resolving @latest, and use the isolated headless mode by default. Only use the shared browser profile with a dedicated low-privilege automation account, because it may contain cookies and active login sessions.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (1)

T08 · Insecure Dependencies

Error
Location
SKILL.md:18
Finding
Mutable Playwright MCP Dependency Is Automatically Downloaded and Executed<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:18-25, 37-43`; `references/usage-patterns.md:3-10`; `scripts/validate.sh:40-49` **Vulnerability Type**: Unpinned runtime dependency and automatic remote package execution **Risk Level**: High ### Vulnerable Code `SKILL.md:18-25`: ```markdown Endpoint candidate inputs before finalizing: - Raw package form from docs: `npx @playwright/mcp@latest` - Reliable non-interactive form: `npx -y @playwright/mcp@latest` - Isolated/headless stable form (default for this skill): - `npx -y @playwright/mcp@latest --headless --isolated` - Shared-profile headless form (for persistent login state): - `npx -y @playwright/mcp@latest --headless --user-data-dir ~/.uxc/playwright-profile` - Shared-profile headed form (for interactive debug with same login state): - `npx -y @playwright/mcp@latest --user-data-dir ~/.uxc/playwright-profile` ``` `SKILL.md:37-43`: ```markdown 3. Use fixed link command by default: - `command -v playwright-mcp-cli` - If missing, create it: - `uxc link playwright-mcp-cli "npx -y @playwright/mcp@latest --headless --isolated"` - Optional shared-profile dual command setup for persistent sessions: - `command -v playwright-mcp-headless` - `command -v playwright-mcp-ui` ``` `references/usage-patterns.md:3-10`: ```markdown All commands in this skill use the fixed stdio endpoint: `npx -y @playwright/mcp@latest --headless --isolated` This skill defaults to fixed link command `playwright-mcp-cli`. Create it when missing: ```bash command -v playwright-mcp-cli uxc link playwright-mcp-cli "npx -y @playwright/mcp@latest --headless --isolated" ``` ``` `scripts/validate.sh:40-49`: ```bash if ! rg -q 'npx -y @playwright/mcp@latest --headless --isolated' "${SKILL_FILE}"; then fail "SKILL.md must document fixed Playwright MCP stdio endpoint" fi if ! rg -q 'command -v playwright-mcp-cli' "${SKILL_FILE}"; then fail "SKILL.md must include link command existence check" f ...[truncated 2806 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace every `@latest` reference with an exact, reviewed version, for example: ```bash npx -y @playwright/mcp@<reviewed-exact-version> --headless --isolated ``` Do not use version ranges, mutable tags, or unspecified versions. 2. Prefer installing dependencies through a committed lockfile with integrity metadata rather than fetching them dynamically during each skill invocation. 3. Where practical, install the reviewed package during a controlled setup phase and execute the locally installed binary afterward. Runtime operation should not implicitly download new code. 4. Update `scripts/validate.sh` to reject mutable references such as `@latest` and require the approved exact version. The validation should also ensure that every documented invocation uses the same pinned version. 5. Introduce an explicit dependency-update process that includes: - Review of upstream release notes and source changes. - Package provenance and publisher verification. - Lockfile and integrity-hash updates. - Security testing before changing the approved version. 6. Protect shared browser profiles with restrictive filesystem permissions and avoid exposing persistent authenticated profiles to newly updated or unreviewed dependency versions. 7. Consider running browser automation in a sandbox or isolated account with minimal filesystem access, restricted environment variables, and controlled network access to reduce the impact of a compromised dependency. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (21)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This code chunk’s primary purpose is validating that the skill’s markdown and YAML documentation contain specific strings and required files. It uses shell utilities like rg, head, and tail to inspect local files and exits with errors if expected documentation is missing. There is no code here that launches @playwright/mcp, talks to UXC stdio MCP, reuses browser sessions, performs navigation, captures DOM snapshots, or enforces browser action guardrails at runtime. While the validation script is related to the Playwright skill’s packaging/documentation, its actual behavior is materially different from the declared operational purpose of the skill itself, so this chunk is a mismatch.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding
The skill instructs users to run `npx @playwright/mcp@latest`, which fetches and executes whatever code is currently published under that package name. Because `@latest` is mutable, a compromised maintainer account, malicious release, or supply-chain hijack would result in arbitrary code execution on the user's machine at invocation time.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding
Using `npx -y @playwright/mcp@latest` still executes a mutable remote package version without review. The `-y` flag removes interaction, making silent execution easier and reducing the chance a user notices that new code is being fetched and run.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding
The default 'stable' invocation still depends on `@playwright/mcp@latest`, so every run may execute newly published code with full local user privileges. In a browser automation skill, this is especially risky because the tool is expected to access network resources, page content, and potentially authenticated sessions.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding
The shared-profile headless example combines mutable remote code execution with access to a persistent browser profile directory. If the fetched package is malicious, it could exfiltrate cookies, tokens, or saved session data from the shared profile.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding
The headed shared-profile example again runs mutable `@latest` code while attaching to a reusable browser profile. This expands impact beyond ordinary code execution to possible theft or misuse of live authenticated browser state during interactive sessions.

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding
The probe command tells users to execute the unpinned package merely to inspect help output. Even 'harmless' probing still runs the package code, so the first-touch experience itself exposes users to supply-chain compromise.

Session Persistence

Medium
Category
Rogue Agent
Content
- `@playwright/mcp` default flow is no OAuth/API key for local stdio use.
3. Use fixed link command by default:
   - `command -v playwright-mcp-cli`
   - If missing, create it:
     - `uxc link playwright-mcp-cli "npx -y @playwright/mcp@latest --headless --isolated"`
   - Optional shared-profile dual command setup for persistent sessions:
     - `command -v playwright-mcp-headless`
Confidence
88% confidence
Finding
The skill explicitly encourages persistent session reuse via shared `--user-data-dir` profiles and daemon-linked commands. Persistent browser profiles can retain cookies, tokens, and other sensitive artifacts, so misuse, local compromise, or accidental cross-task reuse could expose authenticated state beyond the intended session.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding
The `uxc link` command persists a launcher that always resolves to `@playwright/mcp@latest`, effectively baking an ongoing remote-code-execution risk into a reusable local command. Future invocations may silently start running different code than what was originally reviewed.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding
The daemon-exclusive shared-profile headless link combines three risk factors: unpinned remote code, background reuse, and access to persistent browser state. A malicious package update could repeatedly execute in a context that has stable access to stored sessions and profile artifacts.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding
The headed daemon-exclusive link has the same supply-chain exposure as other `@latest` invocations, but with potentially more sensitive interactive state available. Because it is intended for persistent login reuse, compromise could directly impact authenticated accounts and user data.

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding
The documented equivalence to `uxc "npx -y @playwright/mcp@latest --headless --isolated"` normalizes repeated use of a mutable package reference. Even with `--isolated`, the main issue remains arbitrary code execution from an unpinned dependency at runtime.

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding
The skill repeatedly invokes `npx -y @playwright/mcp@latest`, which fetches and executes the latest package version at runtime instead of a pinned, reviewed release. This creates a supply-chain risk: a compromised upstream package, malicious publish, or breaking update would be executed automatically in the user's environment.

Session Persistence

Medium
Category
Rogue Agent
Content
`npx -y @playwright/mcp@latest --headless --isolated`

This skill defaults to fixed link command `playwright-mcp-cli`.
Create it when missing:

```bash
command -v playwright-mcp-cli
Confidence
91% confidence
Finding
The skill explicitly documents persistent login/session reuse via `--user-data-dir ~/.uxc/playwright-profile`, which stores browser cookies and authenticated state across runs. While useful operationally, this increases risk because any later automation command, compromised package, or local user with access to that directory could leverage existing authenticated sessions.

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding
This command configures a reusable CLI link that will later execute `@playwright/mcp@latest`, so the unpinned remote code execution risk is persisted into future use. Because the linked command becomes a stable local alias, users may treat it as trusted while it still resolves to whatever code is currently published upstream.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding
The headless shared-profile command uses `@latest`, combining automatic remote package updates with access to a persistent browser profile. If the upstream package were compromised, malicious code could execute in a context that may contain authenticated session state, cookies, and other sensitive browser data.

Rp1

Medium
Category
MCP Rug Pull
Confidence
98% confidence
Finding
The UI shared-profile command also executes `@playwright/mcp@latest` against a persistent user-data directory. This increases the blast radius of any upstream compromise because an attacker-controlled package could access or manipulate stored browser state and authenticated sessions.

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding
The documented fallback directly runs `uxc "npx -y @playwright/mcp@latest ..."`, preserving the same unpinned execution path even when link setup is unavailable. This means the insecure behavior is not incidental but embedded as a standard operational pattern throughout the skill.

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.

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.

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.

Static analysis

No suspicious patterns detected.