Back to skill

Security audit

Sniplink

Security checks for vulnerabilities and agentic risk

Overview

SnipLink is a coherent URL-saving skill, but it needs review because it writes persistent notes to a hardcoded Google Drive-backed Obsidian path and uses external services without enough user-controlled scoping.

Review this before installing. Configure your own storage location instead of the hardcoded Google Drive path, require confirmation of the exact destination and final filename before saving, and avoid the FxTwitter path unless you are comfortable sharing the tweet URL with that third party. Treat metadata from saved pages as untrusted until the skill adds strict filename and Markdown/YAML sanitization.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

other

Warning
Location
SKILL.md:78
Finding
Undisclosed Third-Party Disclosure of X/Twitter URLs<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 78-85 **Vulnerability Type**: Third-Party Privacy Disclosure **Risk Level**: Medium ### Vulnerable Code ```markdown **Step 1: Extract tweet content (use fxtwitter API first)** - Primary method: `curl -sL "https://api.fxtwitter.com/{user}/status/{id}"` - Returns JSON with `tweet.text`, `tweet.author`, `tweet.media`, `tweet.raw_text.facets` (links inside tweet) - Works without browser, no login, no CAPTCHA — fast and reliable - Extract username and ID from URL patterns: `x.com/{user}/status/{id}` or `twitter.com/{user}/status/{id}` or `x.com/i/status/{id}` - If fxtwitter fails, fallback to browser: `browser_navigate` to the tweet URL + snapshot - If both fail, tell the user the tweet is unreachable and ask them to paste the text ``` ### Technical Analysis The Skill instructs the agent to submit every requested X/Twitter username and status identifier to `api.fxtwitter.com`, an unofficial third-party service. The workflow does not require informing the user that the submitted URL will be disclosed to this service or obtaining consent for that disclosure. Although the request does not explicitly contain authentication credentials, it reveals the exact account and post being accessed. Combined with request timestamps, source IP information, and other server-side telemetry, this can expose the user's browsing interests and activity patterns. The use of `curl -L` follows redirects automatically. If the third-party endpoint redirects to another host, the post identifier will also be disclosed to the redirect destination. This network access is functionally useful for tweet extraction, but automatically selecting an unofficial intermediary exceeds the minimum privacy-preserving behavior necessary for URL storage. ### Attack Path 1. A user submits an X/Twitter URL and asks the Skill to save it. 2. The Skill extracts the username and status identifier from the URL. 3. It sends those values ...[truncated 753 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Inform the user before sending an X/Twitter URL to an unofficial third-party service. 2. Require explicit opt-in consent before the first FxTwitter request. 3. Offer a privacy-preserving alternative, such as direct retrieval from the original site or asking the user to paste the tweet text. 4. Make third-party extraction configurable rather than the mandatory primary method. 5. Avoid following cross-origin redirects automatically. Validate that redirects remain on an approved host before proceeding. 6. Minimize request metadata and do not send cookies, authorization headers, or unrelated query parameters. 7. Document the third party, the data sent to it, and its privacy implications. 8. Treat all metadata returned by the service as untrusted input. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:166
Finding
Hardcoded Personal Google Drive Vault Path<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 166-176 **Vulnerability Type**: Hardcoded Personal Data and Unsafe Storage Configuration **Risk Level**: Medium ### Vulnerable Code ```markdown ## Storage: Obsidian (Single Source of Truth) SnipLink stores all saved tools as Obsidian notes in the user's vault. This centralizes all knowledge in one place and enables graph connections between tools, projects, and concepts. ### Vault Location `~/Library/CloudStorage/GoogleDrive-abdulrahmanjahfali@gmail.com/My Drive/My Mind/SnipLink/` ### Structure - One markdown note per saved tool: `SnipLink/{Tool Name}.md` - Master index: `SnipLink/SnipLink Index.md` ``` ### Technical Analysis The Skill embeds a personal email address and a user-specific Google Drive-backed filesystem location directly in its instructions. This unnecessarily exposes personally identifying information in the distributed Skill and assumes that every installation should use the named account and directory. The workflow does not require the active user to select or verify the vault destination. If the path exists on a shared or transferred system, approved records could be written to an unintended person's cloud-synchronized storage. Conversely, on systems where it does not exist, attempts to create or use it may expose the embedded identity through logs or error messages. Because the destination is cloud synchronized, saved URLs, descriptions, social links, contact information, and source-post references can leave the local machine. The Skill does not explicitly disclose this synchronization consequence when requesting approval to save a record. ### Attack Path 1. A user invokes the Skill and approves a URL record. 2. The agent follows the hardcoded vault location rather than obtaining a user-selected destination. 3. The record is written under the Google Drive directory associated with the embedded email address, if accessible. 4. Google Drive synchronizes the note a ...[truncated 533 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the personal email address and hardcoded absolute vault location from the Skill. 2. Ask each user to select an Obsidian vault and destination folder during initial setup. 3. Store the selected location in a user-specific configuration mechanism rather than in the distributed Skill. 4. Display the resolved destination before the first write and require confirmation. 5. Clearly disclose whether the selected directory is synchronized to a cloud provider. 6. Resolve and canonicalize the configured path before use. 7. Verify that all note and index writes remain inside the user-approved vault directory. 8. Fail safely if the configured vault is absent, inaccessible, or owned by another account; do not silently create a directory based on the hardcoded identity. 9. Avoid including personal identifiers in logs, errors, examples, or default configuration. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:173
Finding
Untrusted Page Metadata Used in Filenames and Obsidian Note Content Without Required Sanitization<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 173-202 **Vulnerability Type**: Path Traversal and Markdown/YAML Injection **Risk Level**: High ### Vulnerable Code ```markdown ### Structure - One markdown note per saved tool: `SnipLink/{Tool Name}.md` - Master index: `SnipLink/SnipLink Index.md` ### Record Format (Obsidian Note) ```markdown --- title: Tool Name url: https://example.com category: Development tags: [python, api, free] price: "Free / $X/mo" saved: 2026-04-04 --- # Tool Name Description of what it does. ## Details - **Use case:** What it's used for - **Notes:** Extra info, source, stats ## Contact - **Email:** ... - **Website:** ... ## Social - [LinkedIn](...) - [Twitter](...) ``` ``` The only specified URL sanitization is elsewhere in the file: ```markdown **Sanitization:** - Strip tracking params from URLs before saving (utm_*, fbclid, etc.) - Never store OAuth tokens, API keys, or session IDs ``` ### Technical Analysis The Skill derives a note filename from `{Tool Name}` and inserts remotely obtained titles, descriptions, tags, prices, contact details, and URLs into YAML and Markdown. It does not require filename normalization, path containment checks, YAML-safe serialization, or Markdown/wiki-link escaping. A malicious page can control metadata returned during extraction. A crafted title containing path separators, traversal sequences such as `../`, absolute-path syntax, or platform-specific reserved characters could alter the intended destination if the storage tool uses the title directly. Similarly, unescaped values can terminate or modify YAML front matter, inject new fields, introduce deceptive Markdown links, or manipulate Obsidian wiki-link and rendering behavior. User approval provides some mitigation, but a clean summary does not necessarily reveal path-control characters or structural payloads, and the workflow does not require showing the final filename or serialized note. ### Attack Path 1. An ...[truncated 1481 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never use a remote page title directly as a filename. 2. Generate filenames using a strict allowlisted slug routine: - Permit only a conservative set of letters, numbers, spaces, hyphens, and underscores. - Remove control characters and Unicode direction-control characters. - Reject or replace `/`, `\`, `..`, drive prefixes, leading tildes, and absolute-path syntax. - Handle reserved platform filenames and enforce a safe maximum length. 3. Resolve the destination to a canonical path and verify that it remains beneath the configured `SnipLink` directory before every write. 4. Use collision-safe file creation rather than silently overwriting an existing note. 5. Serialize front matter through a YAML library instead of string interpolation. 6. Quote and escape every externally derived YAML scalar, including titles, URLs, tags, categories, and prices. 7. Escape or sanitize Markdown and Obsidian wiki-link syntax according to the output context. 8. Restrict URL schemes to an allowlist such as `https` and, where necessary, `http`; reject active or local schemes. 9. Show the final normalized filename, destination, and serialized fields during mandatory approval. 10. Treat metadata from `web_fetch`, GitHub, search results, FxTwitter, and target websites as untrusted, even when it comes from a well-known domain. 11. Add tests covering path traversal, absolute paths, malformed YAML, embedded front-matter delimiters, Markdown link injection, Unicode control characters, and filename collisions. ]]>
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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Vague Triggers

Medium
Confidence
93% confidence
Finding
The trigger section includes phrases like "save this," "remember this," and broad conditions such as asking "what tools do I have for X," which are common conversational requests and not specific to this skill. The file does not provide exclusion conditions or tighter scope boundaries to reduce accidental invocation.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The manifest describes a low-friction URL saving skill that categorizes, tags, and stores links the user provides. Adding a separate capability to search the web for social profiles, and later to suggest tools by tag/category, expands the skill into discovery/recommendation behavior that is not necessary to save a submitted link.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill sends user-provided tweet URLs and derived tweet content to external services such as fxtwitter, and may also perform web searches for enrichment, without a clear privacy disclosure. Users may share links expecting local processing, but the workflow transmits data to third parties, creating privacy, logging, and compliance risks.

External Transmission

Medium
Category
Data Exfiltration
Content
**Trigger:** User shares an `x.com` or `twitter.com` URL and wants it saved.

**Step 1: Extract tweet content (use fxtwitter API first)**
- Primary method: `curl -sL "https://api.fxtwitter.com/{user}/status/{id}"`
  - Returns JSON with `tweet.text`, `tweet.author`, `tweet.media`, `tweet.raw_text.facets` (links inside tweet)
  - Works without browser, no login, no CAPTCHA — fast and reliable
- Extract username and ID from URL patterns: `x.com/{user}/status/{id}` or `twitter.com/{user}/status/{id}` or `x.com/i/status/{id}`
Confidence
91% confidence
Finding
The skill explicitly transmits tweet identifiers and requests extracted tweet content from an external API endpoint. Even if the content is public, this is still an external data flow that can expose user activity, be logged by the third party, and surprise users if not transparently disclosed and consented to.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill writes files into the user's Obsidian vault and updates an index, but this side effect is not clearly disclosed up front in the user-facing description. That can lead to unintended persistent writes in a sensitive knowledge base, especially because the storage is synced and may propagate beyond the local machine.

Ssd 3

Medium
Confidence
99% confidence
Finding
The hardcoded vault path exposes a personal email address and directs writes into a Google Drive-synced location. This leaks personal information in the skill itself and increases the blast radius of any saved content because files are automatically replicated to a third-party cloud service.

Static analysis

No suspicious patterns detected.