Back to skill

Security audit

Bookmark Organize

Security checks for vulnerabilities and agentic risk

Overview

This skill has a legitimate bookmark-organizing purpose, but it exposes powerful Chrome bookmark access through under-protected local and extension messaging channels.

Install only if you are comfortable granting a local unpacked Chrome extension access to your bookmarks and running a localhost bridge. Use it in a low-risk Chrome profile or after exporting a bookmark backup, stop the bridge when finished, and be aware that another local process or extension may be able to interact with the exposed control paths until the implementation adds authentication and sender validation.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
bridges/local-bridge-server.mjs:14
Finding

Unauthenticated Local Bridge Exposes Bookmark Data and Mutation Operations

Content
View full analysis
{ try { if (req.method === "GET" && req.url === "/health") { return sendJson(res, 200, buildHealthPayload()); } if (req.method === "POST" && req.url === "/context") { return sendJson(res, 200, await forwardToExecutor({ type: "bridge.context", ...(await readJsonBody(req)) })); } if (req.method === "POST" && req.url === "/validate") { return sendJson(res, 200, await forwardToExecutor({ type: "bridge.validate", ...(await readJsonBody(req)) })); } if (req.method === "POST" && req.url === "/apply") { return sendJson(res, 200, await forwardToExecutor({ type: "bridge.apply", ...(await readJsonBody(req)) })); } if (req.method === "POST" && req.url === "/undo") { return sendJson(res, 200, await forwardToExecutor({ type: "bridge.undo", ...(await readJsonBody(req)) })); } if (req.method === "POST" && req.url === "/cleanup-test-artifacts") { return sendJson(res, 200, await forwardToExecutor({ type: "bridge.cleanup_test_artifacts", ...(await readJsonBody(req)) })); } ``` ```js server.on("upgrade", (req, socket, head) => { if (req.url !== "/ws") { socket.destroy(); return; } wss.handleUpgrade(req, socket, head, (ws) => { wss.emit("connection", ws, req); }); }); wss.on("connection", (ws) => { ws.on("message", (raw) => { let payload; try { payload = JSON.parse(String(raw)); } catch (error) { return; } if (payload?.type === "hello" && payload?.role === "chrome-executor") { executorSocket = ws; lastExecutorSeenAt = Date.now(); ...[truncated 4005 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
apps/chrome-executor-extension/background.js:31
Finding

External Extension Messages Can Invoke Privileged Bookmark Operations Without Sender Validation

Content
View full analysis
{ handleBridgeMessage(message) .then(sendResponse) .catch((error) => sendResponse(toErrorResponse("INTERNAL_EXECUTION_ERROR", error?.message || String(error)))); return true; }); chrome.runtime.onMessageExternal.addListener((message, sender, sendResponse) => { handleBridgeMessage(message) .then(sendResponse) .catch((error) => sendResponse(toErrorResponse("INTERNAL_EXECUTION_ERROR", error?.message || String(error)))); return true; }); async function handleBridgeMessage(message) { switch (message?.type) { case "bridge.health": return health(); case "bridge.context": return context(message.scope); case "bridge.validate": return validate(message.actions || []); case "bridge.apply": return apply(message.actions || []); case "bridge.undo": return undo(message.undoToken); case "bridge.cleanup_test_artifacts": return cleanupTestArtifacts(); default: return toErrorResponse("INVALID_ACTION_PLAN", `Unsupported bridge message: ${String(message?.type || "unknown")}`); } } ``` ```js async function context(scope) { const tree = await getBookmarkTree(); const normalized = flattenBookmarkTree(tree); return { bookmarks: normalized.bookmarks, folders: normalized.folders, scope: scope || { type: "all", label: "All bookmarks" } }; } ``` The returned bookmark objects include full URLs and metadata: ```js if (node.url) { bookmarks.push({ id: node.id, title, url: node.url, path: parentPath, parentId: node.parentId || "0", index: node.index }); return; } ``` ### Technical Analysis The extension registers `chrome ...[truncated 2295 chars]
Remediation
View remediation
{ if (!sender.id || !TRUSTED_EXTENSION_IDS.has(sender.id)) { sendResponse({ error: { code: "UNAUTHORIZED", message: "Unauthorized sender." } }); return false; } // Continue with authenticated processing. }); ``` 3. Separate read-only operations from mutation operations and apply stricter authorization to the latter. 4. Require short-lived, single-use authorization tokens for `bridge.apply`, `bridge.undo`, and cleanup requests. 5. Bind mutation authorization to the exact validated plan and explicit user confirmation. 6. Validate message schemas, field lengths, action counts, and supported action types before dispatch. 7. Avoid returning full bookmark URLs unless required for the current operation; support minimized or scoped context responses. 8. Add automated tests proving that unknown extension IDs cannot read or mutate bookmarks. ]]>

T08 · Insecure Dependencies

Warning
Location
package.json:14
Finding

Automatic Installation Uses an Unlocked Floating Dependency

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (28)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents conservative bookmark organization, but the analyzed behavior reportedly includes undeclared external messaging, persistent WebSocket connectivity, and deletion capability via cleanup routines. Undeclared communication channels and destructive operations materially expand the attack surface beyond user expectations and could enable unintended modification or abuse of browser data.

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
When this skill says `<skill-folder>`, use the installed ClawHub skill folder containing this `SKILL.md` file.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
When this skill says `<skill-folder>`, use the installed ClawHub skill folder containing this `SKILL.md` file.

Instruction Override

High
Category
Prompt Injection
Confidence
79% confidence
Finding

The skill instructs the host to guide the user through enabling Chrome Developer Mode and loading an unpacked extension. That is a sensitive trust-escalation step because unpacked extensions bypass normal store review and can gain broad browser privileges; embedding these instructions in a user-invocable skill increases the chance of social-engineering users into weakening browser security.

Content

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

md
1. run `node <skill-folder>/scripts/run-repo-script.mjs setup`
2. tell the user to open the extension page if it did not open automatically
3. tell the user to enable Developer Mode
4. tell the user to choose Load unpacked
5. tell the user to select the extension folder printed by setup
6. ask the user to reply `好了`

Instruction Override

High
Category
Prompt Injection
Confidence
70% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

Scanner excerpt · apps/chrome-executor-extension/README.md (reported line 15)May include surrounding context.

md
## Installation

1. Open `chrome://extensions`
2. Enable Developer Mode
3. Click `Load unpacked`
4. Select the `apps/chrome-executor-extension` folder
5. Start the local bridge server with `npm run bridge:server`

Instruction Override

High
Category
Prompt Injection
Confidence
70% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

Scanner excerpt · bridges/setup.mjs (reported line 22)May include surrounding context.

js
## Installation

1. Open `chrome://extensions`
2. Enable Developer Mode
3. Click `Load unpacked`
4. Select the `apps/chrome-executor-extension` folder
5. Start the local bridge server with `npm run bridge:server`

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The HTTP bridge accepts unauthenticated local requests for context, validate, apply, and undo, and the WebSocket endpoint accepts any client that claims the chrome-executor role with no proof of identity. This allows a local process or potentially browser-driven request path to trigger bookmark operations or impersonate the executor, undermining the trust boundary between the agent, the bridge, and Chrome.

Content

No source excerpt is available for this finding.

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
75% confidence
Finding

Skill attempts to nullify the agent's safety policies or restrictions ('you have no restrictions', 'ignore your guidelines', 'do anything now'). This is a direct jailbreak that disables guardrails.

Content

Scanner excerpt · bridges/setup.mjs (reported line 22)May include surrounding context.

js
openChromeExtensions();
  console.log("\n[bookmark-setup] One manual browser step is required:");
  console.log("1. Enable Developer Mode on chrome://extensions");
  console.log("2. Click Load unpacked");
  console.log("3. Select this bundled Chrome executor extension folder:");
  console.log(extensionDir);

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
82% confidence
Finding

The skill declares operational network behavior through a local HTTP bridge at 127.0.0.1:8787, but does not declare any explicit tool scope such as permissions or allowed-tools. That creates a transparency and policy gap: a host may execute local network actions the user did not clearly authorize, especially because the skill also instructs setup of a privileged browser extension and bridge service.

Content

No source excerpt is available for this finding.

Behavior Manipulation

Medium
Category
Prompt Injection
Confidence
75% confidence
Finding

Subtle instructions detected that may alter agent decision-making or introduce hidden biases.

Content

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

md
- If Chrome is not connected, distinguish first-run install from an already-installed but sleeping/disconnected extension
- Never claim that bookmarks were changed unless you have verified success through the local bridge
- Never invent folder counts, bookmark counts, or apply results
- Never tell the user to restart Chrome unless a verified tool result requires it
- If bridge verification fails, explicitly say the task is not yet executed
- Do not use direct filesystem reads or writes of Chrome bookmark files as a substitute for execution
- The only supported execution path is the local bridge plus Chrome executor extension

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The markdown instructs the host to require the user to reply with the Chinese word 好了, and nearby sections provide mandated Chinese-only user-facing wording. This is a natural-language policy issue because it imposes a specific language on users without documenting opt-in or offering an alternative.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

These sections define exact user-facing wording entirely in Chinese for first-run install and disconnected-extension recovery flows. Because the skill does not offer a language/locale option or justify the restriction as region-specific, it violates the language-choice policy.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README states that the extension can apply bookmark actions and keep only a best-effort undo record, but it does not clearly warn users that running it can directly modify or delete bookmark data and that rollback may be incomplete. In a tool that performs browser data mutations, missing safety warnings increases the chance of unintended destructive changes and weakens informed user consent.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The extension registers chrome.runtime.onMessageExternal and forwards any received message into the same privileged bookmark read/write handler used internally, with no sender allowlist, origin verification, or capability restriction shown here. That means another extension able to message this one could read bookmark structure, modify bookmarks, and invoke cleanup/undo flows, expanding access beyond the stated local bridge model.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The context handler returns the full normalized bookmark inventory, and this data is reachable through the bridge mechanisms without any user-visible disclosure or per-request consent in this file. Bookmark trees can reveal sensitive browsing interests, internal URLs, project names, and account structure, so silent export to a bridge process increases privacy risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code applies bookmark creates, moves, renames, and deletions, including irreversible cleanup via bookmarksRemoveTree, but the only user-visible feedback is internal return values and console logging on install. There is no confirmation prompt, visible disclosure, or explanatory comment/docstring in this file warning that external messages can trigger bookmark changes and deletion operations.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The code maintains a persistent WebSocket control channel to a configurable local endpoint and accepts request messages that can read and mutate bookmarks. Even though the default target is localhost, this still creates a privileged IPC surface; if the local bridge service or stored URL is tampered with, bookmark data and mutation capability can be abused without browser UI mediation.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The bridge exposes a cleanup endpoint that goes beyond the stated conservative bookmark organization scope, increasing the attack surface and enabling operations a caller may not expect. In this file, all POST routes are forwarded without authentication or authorization checks, so any additional executor action meaningfully increases the consequences of local or browser-originated abuse.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The bridge sets Access-Control-Allow-Origin to '*' and allows POST requests, enabling arbitrary web pages to issue cross-origin requests to the local service. Because the exposed endpoints can forward state-changing actions to the executor, this turns a localhost service into a browser-accessible control plane and materially increases exploitability.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The bridge exposes cross-origin state-changing endpoints for apply, undo, and cleanup without any user-visible warning, consent gate, or origin restrictions. In the context of a bookmark-management skill that claims conservative, explicit-confirmation behavior, this creates a mismatch where remote page content may be able to trigger privileged local actions without the expected confirmation boundary.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The preflight routine uses AppleScript and fixed screen-coordinate clicks to drive Chrome's UI, which gives the skill a general-purpose capability to manipulate the browser outside the narrowly scoped bookmark API flow. Even though the current script targets chrome://extensions/ to reload the executor, UI scripting is brittle and can misfire if focus, layout, permissions, or window contents differ, potentially causing unintended clicks or actions in the user's browser session.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The AppleScript checks specifically for the window title string "扩展程序 - Google Chrome", which hard-codes a particular UI language/locale. This can violate language/locale policy because the skill behavior depends on a forced locale assumption rather than offering user choice or documenting a justified regional constraint.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The setup script invokes AppleScript via osascript to activate Google Chrome and open chrome://extensions/, which is host-level GUI automation outside the narrow scope of pure bookmark organization. While the current script only opens an internal Chrome page, this establishes a broader automation capability and normalizes local browser control during setup, increasing risk if the script is modified or reused.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The instruction says the user should reply with 已安装 or installed, which constrains the interaction to fixed phrases rather than openly supporting the user's preferred language. While partially bilingual, it still imposes specific language forms without stating broader language flexibility.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

When the bridge is unavailable, the script spawns a background Node process to run a local server. Although related to the bridge, launching detached processes is a general host-control capability that is not clearly justified by the manifest's user-facing purpose of conservative bookmark cleanup and organization.

Content

No source excerpt is available for this finding.