Back to skill

Security audit

Wip Grok

Security checks for vulnerabilities and agentic risk

Overview

This Grok API skill is mostly coherent, but its image-editing path can read arbitrary local files without tight validation or clear MCP disclosure.

Review before installing if you will expose the MCP server to autonomous agents or untrusted prompts. Use a dedicated API key, prefer setting XAI_API_KEY explicitly, avoid relying on automatic 1Password lookup unless intended, and do not pass sensitive local file paths to the image-editing tool. The local-file image behavior should be constrained or confirmed before use in higher-trust environments.

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

T09 · Insecure Skill Coding Practices

Warning
Location
core.mjs:242
Finding
Unrestricted Local File Read Exposed Through the MCP Image-Editing Tool## Vulnerability Details **File Location**: `core.mjs:242-273`; reachable through `mcp-server.mjs:68-76` and `mcp-server.mjs:136-138` **Vulnerability Type**: Unrestricted filesystem access and resource-exhaustion risk **Risk Level**: Medium ### Vulnerable Code `core.mjs:242-273`: ```javascript if (!prompt) throw new Error('prompt is required'); if (!image) throw new Error('image is required (URL or base64 data URI)'); const images = Array.isArray(image) ? image : [image]; if (images.length > 3) throw new Error('Maximum 3 source images'); // Build input with image(s) + text prompt const content = []; for (const img of images) { // If it looks like a file path, read and base64 encode let imageUrl = img; if (!img.startsWith('http') && !img.startsWith('data:')) { const data = readFileSync(img); const ext = img.split('.').pop().toLowerCase(); const mime = ext === 'png' ? 'image/png' : ext === 'webp' ? 'image/webp' : 'image/jpeg'; imageUrl = `data:${mime};base64,${data.toString('base64')}`; } content.push({ type: 'image_url', image_url: { url: imageUrl } }); } content.push({ type: 'text', text: prompt }); const response = await fetch(`${API_BASE}/images/edits`, { method: 'POST', headers: headers(), body: JSON.stringify({ model, image: images[0], prompt, n, response_format, }), }); ``` `mcp-server.mjs:68-76`: ```javascript { name: 'grok_edit_image', description: 'Edit images using natural language with Grok Imagine. Provide source image URL and edit instruction.', inputSchema: { type: 'object', properties: { prompt: { type: 'string', description: 'Edit instruction' }, image: { type: 'string', description: 'Source image URL or base64 data URI' }, }, required: ['prompt', 'image'], }, }, ``` `mcp-server.mjs:136-138`: ```javascript case 'grok_edit_image': result = ...[truncated 3204 chars]
Remediation
## Remediation Suggestions 1. Enforce the documented MCP contract by accepting only explicitly validated HTTPS URLs and approved image data URIs: - Parse URLs with the platform URL parser. - Require the `https:` protocol. - Validate data-URI media types against an image allowlist. - Reject all other strings instead of treating them as paths. 2. If local-file editing is intentionally supported, expose it as an explicit, separately documented capability: - Require user confirmation before reading a local file. - Resolve the supplied path with `realpath`. - Restrict resolved paths to a dedicated user-approved media directory. - Reject path traversal, symbolic-link escapes, devices, sockets, FIFOs, and other non-regular files. - Verify file signatures rather than trusting filename extensions. - Enforce strict byte-size limits before reading. - Use asynchronous file operations to avoid blocking the MCP event loop. 3. Correct the outbound request construction. Send the validated or encoded image value rather than the original path: ```javascript body: JSON.stringify({ model, image: validatedImageUrl, prompt, n, response_format, }); ``` 4. Remove the unused `content` construction if the xAI endpoint does not require it. Avoid reading any file unless its bytes will be used for the requested and authorized operation. 5. Add tests covering arbitrary absolute paths, traversal paths, symbolic links, oversized files, special files, malformed data URIs, unsupported URL schemes, and MCP schema bypass attempts.
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (16)

Missing User Warnings

High
Confidence
99% confidence
Finding
Local files supplied to edit_image are read and transformed into data sent to an external API, but there is no explicit warning or consent mechanism. In context, this is more dangerous because the function accepts arbitrary path strings, so accidental misuse or prompt-/input-influenced path selection can exfiltrate sensitive local content.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The README instructs users to paste a broad natural-language prompt that tells an AI coding tool to clone the repository, read files, explain the tool, and then offer integration. This creates an overly permissive invocation pattern that can trigger repository inspection and integration-oriented behavior without explicit scoping, increasing the chance that an agent will over-trust repository content or take unsafe follow-on actions in a real deployment workflow.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The README states that the tool automatically resolves an xAI API key from 1Password or environment variables, but does not prominently warn that using the skill may cause an agent or local process to access sensitive credentials. In an agent context, automatic secret discovery increases the risk of unintended credential use, exposure in logs, or unauthorized third-party API calls, especially because this skill is explicitly designed to connect to external services.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill advertises and depends on network-capable behavior but does not declare an explicit tool scope such as permissions or allowed-tools. That weakens policy enforcement and reviewability, increasing the chance that an agent can invoke network access more broadly than intended or without clear operator awareness.

External Transmission

Medium
Category
Data Exfiltration
Content
homepage: https://github.com/wipcomputer/wip-grok
metadata:
  category: search,media
  api_base: https://api.x.ai/v1
  capabilities:
    - api
    - web-search
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
homepage: https://github.com/wipcomputer/wip-grok
metadata:
  category: search,media
  api_base: https://api.x.ai/v1
  capabilities:
    - api
    - web-search
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The skill invokes a local subprocess to query the 1Password CLI for an API key, which expands its capabilities beyond simple Grok API calls into local secret-store access. Even if intended for convenience, this creates an unnecessary trust boundary crossing: any code path using this helper can access local credentials without explicit user approval or disclosure.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The module imports filesystem access and later uses it to read arbitrary local paths provided to image editing, which is broader than the manifest suggests for an API-centric media skill. This can expose sensitive local files by converting them to base64 and transmitting them to the external xAI API if a caller passes an unintended or attacker-influenced path.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill retrieves credentials through a subprocess without any user-facing disclosure, so operators may not realize the code accesses local secret-management tooling. This weakens informed consent and can violate least-privilege expectations in environments where skills should only use provided runtime secrets.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The search_web function sends the user-provided query to https://api.x.ai/v1/responses, but the code does not include any visible warning, logging, or disclosure that user input is being sent to a third-party service. This is a network transmission of potentially sensitive user data and falls under missing user warnings for code files.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The search_x function transmits the query and optional handle/date filters to xAI's API, but there is no visible warning or disclosure in the code that this information leaves the local environment. For code handling external network calls with user data, some form of user disclosure is expected.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The generate_video function sends user-provided prompt data and optionally an image URL to xAI's video generation service, but the code provides no visible warning that this content is transmitted externally. Because the request may include user-supplied media references and descriptive content, explicit disclosure is warranted.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The grok_edit_image tool accepts a source image URL or base64 data URI and sends it to the underlying edit_image handler, which implies transmission of potentially sensitive user-provided image content to an external service. In this code, there is no confirmation prompt, privacy warning, or disclosure that uploaded image data will be sent off-system.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The grok_generate_video tool supports an optional image URL for image-to-video generation, which means user image data may be sent to a remote provider. The description documents functionality but does not warn users about external transmission of image content or related privacy implications.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The generate_image function sends the provided prompt to xAI's image generation endpoint, but there is no visible notice that prompt content is transmitted to a third-party service. Even when expected by the function purpose, this file lacks an explicit disclosure in code comments or user-facing output.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
The public documentation says the function accepts only image URLs or base64 data URIs, but the implementation also treats other strings as local file paths and reads them from disk. This mismatch is dangerous because callers may not realize that passing a plain string can trigger local file access and outbound exfiltration to the API.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
core.mjs:28

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
core.mjs:22