Back to skill

Security audit

Offload Tasks to LM Studio Models

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent for local LM Studio offloading, but it needs Review because private prompts can be sent to a configurable endpoint and persisted without clear warnings.

Install only if you are comfortable with agents sending selected task text to LM Studio. Keep the API URL on localhost unless you intentionally trust a remote server, avoid using it for secrets or regulated data without a clear policy, and do not enable --log for sensitive prompts.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/lmstudio-api.mjs:45
Finding
Unrestricted API endpoint permits disclosure of private prompts to remote servers<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lmstudio-api.mjs:12, 45-72, 188`; related endpoint handling also appears in `scripts/load.mjs:8-19, 32`, `scripts/unload.mjs:9-32, 60`, and `scripts/test.mjs:9-59, 71` **Vulnerability Type**: Unrestricted network destination and plaintext transmission of potentially sensitive data **Risk Level**: High ### Code Snippet ```javascript const BASE_URL = process.env.LM_STUDIO_API_URL || 'http://127.0.0.1:1234'; ``` ```javascript const url = `${apiUrl.replace(/\/$/, '')}/api/v1/chat`; const payload = { model, input: taskContent, store: true, temperature: parseFloat(temperature), max_output_tokens: parseInt(maxOutputTokens) }; if (previousResponseId) payload.previous_response_id = previousResponseId; let lastError = null; for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) { try { if (logPath) { fs.writeFileSync(logPath, JSON.stringify({ request: payload, attempt }, null, 2) + '\n', { flag: 'a' }); } const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer lmstudio' }, body: JSON.stringify(payload) }); ``` ```javascript else if (arg.startsWith('--api-url=')) options.apiUrl = arg.split('=')[1]; ``` The same unrestricted URL pattern is used by the other helper scripts: ```javascript const BASE_URL = process.env.LM_STUDIO_API_URL || 'http://127.0.0.1:1234'; ``` ```javascript if (arg.startsWith('--api-url=')) apiUrl = arg.split('=')[1]; ``` ### Technical Analysis The Skill declares that processing is local and suitable for privacy-sensitive work, with a default LM Studio URL of `http://127.0.0.1:1234`. However, the destination can be replaced without validation through either the `LM_STUDIO_API_URL` environment variable or the `--api-url` argument. The main chat helper sends the complete task text, model identifier, and optional previous response identifier ...[truncated 2683 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict the default operating mode to loopback destinations such as `127.0.0.1`, `::1`, and `localhost`. 2. Parse endpoints with the standard `URL` class rather than constructing URLs through string concatenation. 3. Reject non-loopback endpoints unless the user supplies a separate, explicit option such as `--allow-remote-api`. 4. Require HTTPS whenever remote access is explicitly enabled. 5. Resolve hostnames and verify that the resolved addresses comply with the intended network policy. Account for IPv4, IPv6, alternative loopback notation, and DNS rebinding. 6. Disable automatic cross-origin redirects or validate the destination of every redirect. 7. Display a clear warning before sending prompt content remotely, explaining that remote mode invalidates the local-only privacy guarantee. 8. Consider removing `--api-url` from normal agent-generated invocations and placing remote endpoint configuration in a trusted administrator-controlled configuration file. 9. Document exactly which fields are transmitted: task text, model identifier, response identifier, and generation settings. 10. Apply the same endpoint validation consistently to `lmstudio-api.mjs`, `load.mjs`, `unload.mjs`, and `test.mjs`. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lmstudio-api.mjs:61
Finding
Optional logging stores complete prompts and responses in unprotected plaintext files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lmstudio-api.mjs:61-78` **Vulnerability Type**: Plaintext sensitive-data logging and unsafe caller-controlled log path **Risk Level**: Medium ### Code Snippet ```javascript if (logPath) { fs.writeFileSync(logPath, JSON.stringify({ request: payload, attempt }, null, 2) + '\n', { flag: 'a' }); } const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer lmstudio' }, body: JSON.stringify(payload) }); const data = await response.json(); if (logPath) { fs.writeFileSync(logPath, JSON.stringify({ response: data, status: response.status }, null, 2) + '\n', { flag: 'a' }); } ``` The path is taken directly from a command-line argument: ```javascript else if (arg.startsWith('--log=')) options.logPath = arg.slice(6); ``` ### Technical Analysis When `--log` is enabled, the helper appends the complete request payload and complete API response to a caller-selected path. The request contains the full task in `payload.input` and can include a stateful conversation identifier. The response may contain generated text, reasoning output, model metadata, and token statistics. The implementation does not redact sensitive fields, set an explicit restrictive file mode, reject symbolic links, constrain logs to a dedicated directory, or establish retention and deletion controls. File accessibility consequently depends on the process umask and surrounding filesystem permissions. Because append mode is used on a caller-controlled path, the script can also append data to any file writable by the invoking user, including a path reached through a symbolic link. Logging is optional and requires explicit use of `--log`, which reduces exploitability. Nevertheless, the feature creates a durable plaintext copy of information that the Skill advertises as appropriate for privacy-sensitive local processing. ### Attack Path 1. A workflow, wrappe ...[truncated 1135 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Log metadata only by default, excluding `input`, response content, reasoning content, and conversation identifiers. 2. Require a separate explicit option, accompanied by a warning, before enabling full-content logging. 3. Create new log files with mode `0600` and verify permissions after creation. 4. Use safe file-opening flags that prevent following symbolic links where supported, and reject paths that resolve to symbolic links. 5. Restrict logs to a dedicated application-owned directory rather than accepting unrestricted filesystem paths. 6. Refuse special files and verify that the destination is a regular file. 7. Add configurable retention, secure deletion guidance, and log rotation. 8. Redact secrets and configurable sensitive patterns before writing any content. 9. Clearly document that enabling full logs creates a persistent plaintext copy and is unsuitable for highly sensitive tasks. 10. Avoid logging complete error responses when they may echo submitted prompt content. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (15)

Ae1

High
Category
analysis-evasion
Content
node scripts/lmstudio-api.mjs <model> '<task>' --temperature=0.5 --max-output-tokens=200
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/lmstudio-api.mjs <model> '<task>' --temperature=0.5 --max-output-tokens=200
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/lmstudio-api.mjs <model> '<task>' --temperature=0.5 --max-output-tokens=200
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/lmstudio-api.mjs <model> '<task>' --temperature=0.5 --max-output-tokens=200
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/lmstudio-api.mjs <model> '<task>' --temperature=0.5 --max-output-tokens=200
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/lmstudio-api.mjs <model> '<task>' --temperature=0.5 --max-output-tokens=200
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
Optional: POST /api/v1/models/load { model, context_length?, ... }. Or run scripts/load.mjs &lt;model&gt;. JIT: first chat loads; explicit load only for specifi
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
ponse only (do not send the model key unless it exactly equals that id). Or run scripts/unload.mjs &lt;model_key&gt; (script does GET then unloads each instance
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Vague Triggers

Medium
Confidence
95% confidence
Finding
The README states the skill is automatically triggered for broad categories like summarization, classification, brainstorming, and first-pass code review, without clear gating criteria or explicit user confirmation. In an agentic system, this can cause unintended invocation of a local model for sensitive or security-relevant tasks, potentially exposing data to an unintended processing path or producing lower-quality security judgments that influence later actions.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill clearly instructs the agent to use network access and local execution (`curl`, `node scripts/...`) but does not declare any explicit tool scope such as allowed tools or permissions. This increases the chance that an agent runtime grants broader capabilities than intended, making misuse or unexpected command/network execution harder to constrain or review.

External Transmission

Medium
Category
Data Exfiltration
Content
## Prerequisites

LM Studio 0.4+, server :1234, models on disk; load/unload via API (JIT optional); Node for script (curl ok).

## Quick start
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill advertises `--log <path>` for request/response logging without warning that prompts, outputs, identifiers, and possibly sensitive task data may be written to disk. In a privacy-sensitive or local-only workflow, silent persistence of full model interactions can create unintended data exposure through log files, backups, or shared workstations.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The --log option appends the full request payload and full API response to an arbitrary file path, which can include sensitive prompts, extracted secrets, private local data, and model outputs. In this skill's context, the tool is explicitly marketed for local-only or privacy-sensitive work, so silent disk persistence of that content increases confidentiality risk if logs are later read by other users, backup systems, or malware.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The smoke test sends a chat request with `store: true`, which explicitly instructs the LM Studio server to retain the conversation. Because this skill is marketed for local-only and privacy-sensitive work, storing even a trivial prompt without disclosure or opt-in can create unexpected data retention and weaken privacy guarantees if the script is reused with nontrivial prompts or against a shared server.

Missing User Warnings

Low
Confidence
82% confidence
Finding
The skill recommends unloading all instances for a model key and even provides automation to do so, but it does not warn that these instances may be shared with other active local workflows. This can disrupt concurrent sessions, terminate in-progress tasks, or cause availability issues for other users/processes on the same machine.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/lmstudio-api.mjs:12

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/load.mjs:8

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/test.mjs:9

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/unload.mjs:9