Back to skill

Security audit

X Bookmarks Digest

Security checks for vulnerabilities and agentic risk

Overview

The skill appears intended to digest X/Twitter bookmarks, but it uses broad triggers to access private account data and may recommend installs or clones from untrusted social posts.

Install only if you are comfortable giving the skill access to your private X/Twitter bookmarks through xurl. Use explicit X/Twitter bookmark commands, review the digest as untrusted input, and independently verify any suggested brew, pip, cargo, git, clawhub, memory, or Obsidian action before approving it.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/analyse_bookmarks.py:121
Finding

Untrusted bookmark content is passed into agent analysis without an explicit instruction boundary

Content
View full analysis
dict: """Analyse a single bookmark and return enriched data.""" text = bookmark.get("text", "") author = bookmark.get("author_username", bookmark.get("username", "unknown")) bm_id = bookmark.get("id", "") created = bookmark.get("created_at", "") # Handle nested author object (X API v2 format with expansions) if isinstance(bookmark.get("author"), dict): author = bookmark["author"].get("username", author) urls = extract_urls(text) # Also check entities.urls if present (X API v2) entities = bookmark.get("entities", {}) if isinstance(entities, dict): for url_entity in entities.get("urls", []): expanded = url_entity.get("expanded_url", "") if expanded and expanded not in urls: urls.append(expanded) github_repos = extract_github_repos(urls) category = categorise(text, urls) relevance = score_relevance(text, urls, category) return { "id": bm_id, "text": text[:500], # Truncate very long tweets "author": f"@{author}" if not author.startswith("@") else author, "created_at": created, "category": category, "relevance": relevance, "urls": urls, "github_repos": github_repos, "keywords": extract_keywords(text), } ``` The related agent instructions consume this output as follows: ```markdown ### Step 3: Analyse Bookmarks Pipe the fetched bookmarks through the analyser: ```bash python3 {baseDir}/scripts/fetch_bookmarks.py --count 50 | python3 {baseDir}/scripts/analyse_bookmarks.py ``` ... ### Step 5: Decide on Actions For each high-value bookmark, decide: | Bookmark Type | Action | |-- ...[truncated 2783 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
references/analysis_criteria.md:28
Finding

Dependency installation recommendations rely on unverified social-media claims and heuristic scoring

Content
View full analysis
` | | **Interesting project to build** | Propose scaffolding a new skill in `skills/` | | **Useful article/thread** | Propose saving to Obsidian vault | | **Tip/technique** | Propose saving to OpenClaw memory | Ask the user which actions to execute. Do not auto-execute without confirmation. ``` ### Technical Analysis The action criteria recommend installing tools or cloning repositories when a bookmark receives a high heuristic score. The scoring implementation uses keywords, category terms, and recognized domains; it does not verify package ownership, publisher identity, repository authenticity, release signatures, checksums, package age, or whether a package name corresponds to the linked official project. An attacker can advertise a typosquatted package, dependency-confusion package, or malicious repository using convincing technical keywords and a recognized hosting domain. Such content can be classified as high value and presented to the user as an installation cand ...[truncated 1445 chars]
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description promises analysis, digest generation, and proposed next steps, while the visible file mostly orchestrates fetch/analyse scripts and state updates without embedding or proving those behaviors in this file. This mismatch can mislead users and security reviewers about what the skill actually does, especially since it includes local persistence and command execution that are not prominently disclosed in the top-level description.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The architecture explicitly contemplates auto-installing skills, scaffolding new ones, cloning repositories, and writing local state without an explicit safety gate or user confirmation for system-modifying actions. In a workflow driven by untrusted bookmark content, this creates a meaningful risk of prompt-to-action chaining where social posts indirectly influence local code installation or filesystem changes.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger list includes generic everyday phrases such as "check my bookmarks" and "review bookmarks," which can cause the skill to activate in unintended contexts. Because this skill can fetch private bookmark data and propose follow-on actions, accidental invocation increases the risk of unnecessary data access and downstream unsafe behavior.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill invokes shell commands, performs network access via xurl, and updates local state.json, but it does not declare any explicit tool scope or permissions boundaries. That makes the effective privileges implicit and broader than a reviewer or runtime policy engine can safely reason about, increasing the chance of unintended command execution or file modification if the skill is triggered in the wrong context.

Content

No source excerpt is available for this finding.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
93% confidence
Finding

The trigger phrase 'review bookmarks' overlaps with a generic built-in 'review' intent, creating a shadowing/confusion risk where this skill could intercept unrelated requests. Because the skill can invoke authenticated network commands and update state, accidental activation is more dangerous than a simple UX issue.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger set includes generic phrases like 'check my bookmarks' and 'review bookmarks' that could match ordinary conversation unrelated to X/Twitter bookmark processing. Overly broad activation raises the risk that the skill will run shell/network workflows unexpectedly, exposing account data or modifying local state when the user did not intend to invoke this capability.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The invocation guidance says to activate on broad requests like 'what's interesting in my bookmarks?' without requiring the user to specify X/Twitter or acknowledge external fetching. Ambiguous activation language increases accidental execution risk because the skill performs authenticated network access and stateful processing rather than a harmless local summary.

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 162)May include surrounding context.

md
| **Useful article/thread** | Propose saving to Obsidian vault |
| **Tip/technique** | Propose saving to OpenClaw memory |

Ask the user which actions to execute. Do not auto-execute without confirmation.

### Step 6: Update State

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% 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 162)May include surrounding context.

md
| **Useful article/thread** | Propose saving to Obsidian vault |
| **Tip/technique** | Propose saving to OpenClaw memory |

Ask the user which actions to execute. Do not auto-execute without confirmation.

### Step 6: Update State

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/fetch_bookmarks.py (reported line 57)May include surrounding context.

python
def fetch_bookmarks(count: int) -> list:
    """Call xurl bookmarks and return parsed JSON list."""
    try:
        result = subprocess.run(
            ["xurl", "bookmarks", "-n", str(count)],
            capture_output=True,
            text=True,

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script reads bookmark content and associated metadata from stdin or a file, then emits the processed text, author handle, URLs, and timestamps in JSON output without any minimization, redaction, or explicit consent/disclosure mechanism. In the context of personal X/Twitter bookmarks, this can expose private or sensitive saved content to downstream tools, logs, or other agents, especially because bookmarks are often treated as a private curation surface by users.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.