Back to skill

Security audit

chrome-extension-wxt

Security checks for vulnerabilities and agentic risk

Overview

This WXT browser-extension documentation skill is coherent and not malicious, but it needs Review because copyable examples cover sensitive browser data, credentials, and mutable package execution without enough guardrails.

Install only if you are comfortable treating this as advanced browser-extension guidance. Before using generated code from it, pin package versions, avoid copying unsafe-eval into production, keep permissions and host patterns narrow, add confirmations for history or cookie changes, and do not store long-lived API keys as ordinary extension state.

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

T08 · Insecure Dependencies

Error
Location
SKILL.md:33
Finding
Unpinned npm and npx Commands Execute Mutable Third-Party Code<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:33-38, 264-267, 277-288`; `references/react-integration.md:10-12, 600-601, 674-675, 687-688` **Vulnerability Type**: Supply-chain exposure through unpinned executable dependencies **Risk Level**: High ### Vulnerable Code ```bash # Create new project with framework of choice npm create wxt@latest # Or with specific template npm create wxt@latest -- --template react-ts npm create wxt@latest -- --template vue-ts npm create wxt@latest -- --template svelte-ts ``` ```bash npm create wxt@latest -- --template react-ts npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p npx shadcn@latest init ``` Additional occurrences include: ```bash npx shadcn@latest init npx shadcn@latest add button card dialog ``` ### Technical Analysis The Skill directs users or an agent to execute packages resolved dynamically from the npm registry. In particular, the `@latest` tag is mutable and does not identify the package version that was reviewed when the Skill was published. Both `npm create` and `npx` can download and execute package code. Package lifecycle scripts and CLI initialization logic run with the privileges of the invoking user. Consequently, the effective code executed by these instructions can change without any modification to this repository. The unversioned `npm install` commands also leave dependency resolution dependent on the package metadata and lockfile generated at execution time. The repository does not supply a reviewed lockfile or integrity metadata because it is a documentation Skill rather than a complete application. ### Attack Path 1. An attacker compromises a referenced npm package, one of its transitive dependencies, its maintainer account, or the associated registry release process. 2. The attacker publishes a malicious version and causes it to be selected by the `latest` tag or an unconstrained dependency range. 3. A user or coding agent follows the Skill and runs ...[truncated 950 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace `@latest` with exact, reviewed package versions, for example: ```bash npm create wxt@X.Y.Z npx --yes shadcn@X.Y.Z init ``` 2. Document the expected package publisher, repository, version, and integrity information. 3. Generate and commit a lockfile for any maintained template or example project. 4. Use `npm ci` for reproducible installation after reviewing the lockfile. 5. Review package lifecycle scripts before installation and consider initially installing with `--ignore-scripts` where compatible. 6. Run project generators in a restricted development container or sandbox without production credentials. 7. Use automated dependency scanning and require manual review before updating pinned versions. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
references/react-integration.md:153
Finding
API Key Is Stored in Browser Synchronization Storage<![CDATA[ ## Vulnerability Details **File Location**: `references/react-integration.md:153-170, 207-216` **Vulnerability Type**: Insecure storage and synchronization of authentication secrets **Risk Level**: High ### Vulnerable Code ```typescript export default function Options() { const [settings, setSettings] = useState({ theme: 'light', notifications: true, apiKey: '', }); useEffect(() => { // Load settings browser.storage.sync.get('settings').then((result) => { if (result.settings) { setSettings(result.settings); } }); }, []); async function handleSave() { await browser.storage.sync.set({ settings }); // Show success notification await browser.notifications.create({ type: 'basic', title: 'Settings Saved', message: 'Your settings have been saved successfully', iconUrl: '/icon/128.png', }); } ``` ```tsx <section> <label> API Key: <input type="password" value={settings.apiKey} onChange={(e) => setSettings({ ...settings, apiKey: e.target.value })} placeholder="Enter your API key" /> </label> </section> ``` ### Technical Analysis The API key is part of the `settings` object, and the entire object is written to `browser.storage.sync`. A password-type input only masks the visible characters in the user interface; it does not encrypt the value in application state or storage. Synchronization storage is intended for preferences that may be replicated through the user's browser account. Treating an API key as an ordinary synchronized preference unnecessarily expands the locations and contexts in which the secret may be available. Any compromised or vulnerable extension component with access to the storage API may retrieve the plaintext value. This conflicts with least-privilege secret handling because the extension's theme and notification preferences do not require the authentication secret to be stored or synchronized alon ...[truncated 1047 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `apiKey` from the synchronized settings object. 2. Store non-sensitive preferences and credentials separately: ```typescript await browser.storage.sync.set({ settings: { theme: settings.theme, notifications: settings.notifications, }, }); await browser.storage.local.set({ apiKey: settings.apiKey, }); ``` 3. Prefer short-lived, narrowly scoped OAuth tokens over long-lived API keys. 4. If the architecture permits it, retain credentials only in memory or use an operating-system-backed credential service through a carefully reviewed native component. 5. Restrict which extension contexts can request or use the credential. 6. Never return the secret through generic message handlers or log it to browser consoles. 7. Provide explicit credential deletion, rotation, and revocation controls. 8. Clearly disclose storage and synchronization behavior in the extension's privacy documentation. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
references/best-practices.md:70
Finding
Bearer Credential Can Be Sent to an Unvalidated Network Destination<![CDATA[ ## Vulnerability Details **File Location**: `references/best-practices.md:70-79` **Vulnerability Type**: Credential disclosure through unrestricted authenticated request destination **Risk Level**: High ### Vulnerable Code ```typescript // Store in browser.storage, not in code const { apiKey } = await browser.storage.local.get('apiKey'); const response = await fetch(url, { headers: { 'Authorization': `Bearer ${apiKey}`, }, }); ``` ### Technical Analysis The example reads an API key from extension storage and attaches it as a bearer credential to `fetch(url)`. The destination is represented by an unrestricted variable, with no validation of its origin, scheme, port, path, or redirect behavior. If `url` is derived from page content, a runtime message, user input, remote configuration, or another untrusted source, an attacker can direct the authenticated request to an attacker-controlled endpoint. The browser will then disclose the API key in the `Authorization` header. Even if the initial URL is approved, permissive redirect handling can create additional risk. Credential forwarding behavior varies according to redirect and origin conditions, so security should not depend solely on implicit browser behavior. The network request may be necessary for an extension that communicates with an API, but attaching credentials to arbitrary destinations exceeds the minimum privilege needed for that functionality. ### Attack Path 1. An extension stores a valid API key under `apiKey`. 2. An attacker gains influence over the `url` value, for example through an unvalidated extension message or page-derived input. 3. The attacker supplies an HTTPS URL under their control. 4. The extension executes the documented `fetch` operation. 5. The request includes `Authorization: Bearer <apiKey>`. 6. The attacker's server records the header and reuses the credential against the legitimate API. ### Impact Assessment This can disclose the complete bearer credent ...[truncated 456 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use a fixed API base URL rather than accepting an arbitrary destination. 2. If configurability is required, parse and validate the URL against an exact allowlist: ```typescript const API_ORIGIN = 'https://api.example.com'; const target = new URL(url); if (target.protocol !== 'https:' || target.origin !== API_ORIGIN) { throw new Error('Unapproved API destination'); } const response = await fetch(target.href, { redirect: 'error', headers: { Authorization: `Bearer ${apiKey}`, }, }); ``` 3. Reject non-HTTPS schemes, unexpected ports, embedded credentials, and lookalike hostnames. 4. Prevent messages from content scripts or web pages from directly selecting authenticated request destinations. 5. Validate message senders, message schemas, and requested API operations in the background service worker. 6. Use narrowly scoped, short-lived credentials and support immediate revocation. 7. Avoid logging request headers or credential-bearing error objects. 8. Declare host permissions only for the exact API origins required by the extension. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/react-integration.md:956
Finding
Extension CSP Guidance Enables Unsafe Dynamic Code Evaluation<![CDATA[ ## Vulnerability Details **File Location**: `references/react-integration.md:956-964`; related examples at `references/react-integration.md:26-33` and `references/best-practices.md:10-17` **Vulnerability Type**: Weak Content Security Policy permitting eval-like execution **Risk Level**: Medium ### Vulnerable Code ```markdown ### Issue: React DevTools not working **Solution:** Add to manifest: ``` ```typescript manifest: { content_security_policy: { extension_pages: "script-src 'self' 'unsafe-eval'; object-src 'self'", }, } ``` Related default guidance also enables WebAssembly evaluation: ```typescript export default defineConfig({ manifest: { content_security_policy: { extension_pages: "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'", }, }, }); ``` ### Technical Analysis The troubleshooting guidance recommends adding `'unsafe-eval'` to the extension-page Content Security Policy. This allows JavaScript string evaluation mechanisms that a restrictive extension CSP is intended to block. If attacker-controlled data reaches an eval-compatible sink, the weakened policy can turn an injection flaw into script execution within an extension page. Extension pages can possess capabilities unavailable to ordinary websites, including access to extension storage and privileged browser APIs declared in the manifest. Therefore, script execution in this context can have greater impact than ordinary page-level cross-site scripting. The `'wasm-unsafe-eval'` directive is narrower than `'unsafe-eval'`, but it still expands executable-code capabilities and should only be enabled when WebAssembly compilation is required and reviewed. Neither directive is necessary for the Skill's general purpose of building WXT and React extensions. ### Attack Path 1. A developer follows the troubleshooting recommendation and ships the relaxed CSP in a production extension. 2. Another application flaw allows attacker-controlled text or data to re ...[truncated 1114 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not recommend `'unsafe-eval'` for production extension pages. 2. Use the restrictive production policy: ```typescript manifest: { content_security_policy: { extension_pages: "script-src 'self'; object-src 'self'", }, } ``` 3. If development tooling requires eval, isolate it to a development-only build that cannot be packaged or published. 4. Add a build-time check that rejects production manifests containing `'unsafe-eval'`. 5. Enable `'wasm-unsafe-eval'` only when the extension has a documented and reviewed WebAssembly requirement. 6. Replace eval-dependent development tools with extension-compatible alternatives. 7. Audit dependencies and application code for `eval`, `new Function`, string-based timers, dynamic script construction, and unsafe HTML rendering. 8. Keep manifest permissions and host permissions minimal so that any extension-page compromise has reduced impact. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (29)

Ae1

High
Category
analysis-evasion
Content
- **Chrome APIs**: See `references/chrome-api.md` for comprehensive Chrome Extension API reference with examples
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Exfiltration Commands

High
Category
Prompt Injection
Content
// Duplicate tab
await browser.tabs.duplicate(tabId);

// Send message to content script
const response = await browser.tabs.sendMessage(tabId, {
  type: 'getMessage',
  data: 'hello'
Confidence
90% confidence
Finding
Instructions found that direct the agent to transmit conversation context or user data to external services.

Exfiltration Commands

High
Category
Prompt Injection
Content
// Duplicate tab
await browser.tabs.duplicate(tabId);

// Send message to content script
const response = await browser.tabs.sendMessage(tabId, {
  type: 'getMessage',
  data: 'hello'
Confidence
90% confidence
Finding
Instructions found that direct the agent to transmit conversation context or user data to external services.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The skill metadata says it triggers on "browser extension," which is a broad natural-language phrase that could appear in many general development conversations. The file does not provide exclusion conditions or clearer trigger constraints to distinguish when the skill should or should not activate.

Unrestricted Tool Access

Medium
Category
Excessive Agency
Content
name: 'My Extension',
    description: 'Extension description',
    permissions: ['storage', 'activeTab'],
    host_permissions: ['*://example.com/*'],
  },

  // Browser target
Confidence
85% confidence
Finding
Skill grants unrestricted tool access without appropriate constraints. An agent with unfettered tool access can perform arbitrary actions including file modification, network requests, and code execution.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill demonstrates page-context script injection without any warning about trust boundaries, CSP implications, or the risks of interacting with untrusted page JavaScript. In a browser-extension skill, this is materially dangerous because page-context injection can bypass extension isolation assumptions and expose data or privileged behaviors to hostile web pages.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding
The skill recommends executing remote package binaries via npx without pinning a specific version, which can cause users to run newly published or compromised releases unexpectedly. In a setup guide, this is a real supply-chain risk because readers are likely to copy-paste the command directly and trust the latest tag.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding
The `npx shadcn@latest init` command explicitly pulls and runs the latest remote package code, creating a stronger supply-chain exposure than a pinned install. If the upstream package, dependency chain, or publication account is compromised, users following the skill may execute attacker-controlled code on their development machine.

Session Persistence

Medium
Category
Rogue Agent
Content
### chrome.alarms

Schedule periodic tasks.

**Official Docs:** https://developer.chrome.com/docs/extensions/reference/api/alarms
Confidence
80% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The webRequest section includes request blocking, header modification, CORS-related response header changes, and redirects without warning about privacy, site-breakage, or security-boundary bypass risks. In a Chrome extension skill, these examples can directly enable interception of user traffic or weakening of browser/web protections if copied into generated code.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The cookie examples show reading, setting, and removing cookies without warning that cookies often contain authentication and session state. In extension-development guidance, this can normalize unsafe handling of sensitive session data and lead developers to build features that expose or alter credentials without adequate safeguards.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The scripting section demonstrates JavaScript and CSS injection into pages, including inline functions, without warning that injected code can read and alter page content and behavior. For an extension-building skill, omission of these caveats increases the risk of generated code that silently inspects user data or tampers with trusted web pages.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The documentation demonstrates browser history search and deletion APIs, including bulk deletion, without warning that these operations access highly sensitive user activity and can irreversibly destroy data. In a browser-extension skill, omission of privacy and destructive-action guidance materially increases the chance that generated extensions will over-collect history or delete it without informed user consent.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The example stores an API key in `browser.storage.sync` without any warning about sensitivity, exposure scope, or safer alternatives. Extension storage is not an appropriate place to casually persist secrets in sample code because it encourages insecure credential handling patterns and can lead to leakage across synced profiles, backups, or other extension-accessible contexts.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This Zustand persistence example stores `apiKey` in `browser.storage.local` as routine application state, normalizing insecure secret persistence. In the browser-extension context, this is particularly risky because developers may copy the pattern directly into production code, exposing long-lived credentials to local compromise, debugging artifacts, or other extension logic that can read storage.

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.

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.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The documentation explicitly recommends adding `'unsafe-eval'` to the extension page CSP to enable React DevTools. Weakening MV3 extension CSP in this way increases the attack surface for script injection and undermines one of the browser extension platform's primary defenses; if any DOM XSS or code-injection primitive exists elsewhere, `'unsafe-eval'` can make exploitation substantially easier.

Scope Creep

Low
Category
Excessive Agency
Content
permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation source, and
configuration files.

"Object" form shall mean any form resulting from mechanical transformation or
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Scope Creep

Low
Category
Excessive Agency
Content
permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation source, and
configuration files.

"Object" form shall mean any form resulting from mechanical transformation or
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Scope Creep

Low
Category
Excessive Agency
Content
permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation source, and
configuration files.

"Object" form shall mean any form resulting from mechanical transformation or
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Scope Creep

Low
Category
Excessive Agency
Content
permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation source, and
configuration files.

"Object" form shall mean any form resulting from mechanical transformation or
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Excessive Permissions

Low
Category
Privilege Escalation
Content
name: 'My Extension',
    description: 'Extension description',
    permissions: ['storage', 'activeTab'],
    host_permissions: ['*://example.com/*'],
  },

  // Browser target
Confidence
80% confidence
Finding
Skill requests more permissions than appear necessary for its stated functionality. Review if elevated access is justified.

Static analysis

No suspicious patterns detected.