Back to skill

Security audit

LLM Signal GEO Analyst

Security checks for vulnerabilities and agentic risk

Overview

This skill’s stated purpose is legitimate, but it lets remote workflow plans trigger automatic actions and sends an API key to a configurable endpoint without enough local safeguards.

Review this skill before installing. Use it only with a trusted LLM Signal endpoint, prefer HTTPS, avoid untrusted or user-editable LLMSIGNAL_BASE_URL values, and treat auto_safe plan items as recommendations unless your OpenClaw environment adds its own approval and allowlist controls. Rotate the API key if it may have been used with an untrusted endpoint.

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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch-plan.sh:4
Finding
API Credential Disclosure to an Unrestricted Network Endpoint## Vulnerability Details **File Location**: `scripts/fetch-plan.sh:4-11`; equivalent behavior occurs in `scripts/fetch-status.sh:4-11` **Vulnerability Type**: Unrestricted transmission of sensitive credentials **Risk Level**: High ### Vulnerable Code `scripts/fetch-plan.sh:4-11`: ```bash : "${LLMSIGNAL_BASE_URL:?Missing LLMSIGNAL_BASE_URL}" : "${LLMSIGNAL_SITE_ID:?Missing LLMSIGNAL_SITE_ID}" : "${LLMSIGNAL_API_KEY:?Missing LLMSIGNAL_API_KEY}" curl -sS -X POST "${LLMSIGNAL_BASE_URL%/}/api/agent/v1/plan" \ -H "Content-Type: application/json" \ -H "X-LLMSIGNAL-KEY: ${LLMSIGNAL_API_KEY}" \ -d "{\"siteId\":\"${LLMSIGNAL_SITE_ID}\",\"apiKey\":\"${LLMSIGNAL_API_KEY}\",\"persist\":true}" ``` `scripts/fetch-status.sh:4-11`: ```bash : "${LLMSIGNAL_BASE_URL:?Missing LLMSIGNAL_BASE_URL}" : "${LLMSIGNAL_SITE_ID:?Missing LLMSIGNAL_SITE_ID}" : "${LLMSIGNAL_API_KEY:?Missing LLMSIGNAL_API_KEY}" curl -sS -X POST "${LLMSIGNAL_BASE_URL%/}/api/agent/v1/status" \ -H "Content-Type: application/json" \ -H "X-LLMSIGNAL-KEY: ${LLMSIGNAL_API_KEY}" \ -d "{\"siteId\":\"${LLMSIGNAL_SITE_ID}\",\"apiKey\":\"${LLMSIGNAL_API_KEY}\"}" ``` ### Technical Analysis Both scripts use the runtime-controlled `LLMSIGNAL_BASE_URL` directly as the destination for authenticated network requests. They do not enforce HTTPS, verify that the hostname belongs to LLM Signal, restrict ports, or explicitly prohibit redirects. The API key is sent twice: once in the `X-LLMSIGNAL-KEY` authentication header and again in the JSON request body. Including the key in the body is not necessary when header authentication is already used and increases exposure to HTTP body logging, reverse proxies, tracing systems, and server-side diagnostics. The network access itself is necessary for the declared hosted GEO workflow. However, permitting an arbitrary destination and transmitting the secret redundantly exceed the minimum privileges needed for that f ...[truncated 1046 chars]
Remediation
## Remediation Suggestions 1. Enforce an HTTPS URL and a strict hostname allowlist before sending credentials. If self-hosting must be supported, require administrators to configure an explicit allowlist rather than accepting any URL. 2. Reject URL user information, unexpected ports, non-HTTPS schemes, malformed hosts, and loopback or private destinations unless explicitly required. 3. Disable redirects or validate every redirect destination: ```bash curl --proto '=https' --tlsv1.2 --max-redirs 0 ... ``` 4. Send the API key only in the authentication header. Remove the `apiKey` property from both JSON payloads and request templates. 5. Keep normal TLS certificate verification enabled and document that disabling certificate validation is unsupported. 6. Use a narrowly scoped, revocable API credential and rotate any credential that may have been sent to an untrusted destination. 7. Avoid logging command arguments, headers, environment variables, or request bodies containing secrets.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fetch-plan.sh:11
Finding
JSON Request Injection Through Unescaped Environment Variables## Vulnerability Details **File Location**: `scripts/fetch-plan.sh:11`; equivalent behavior occurs in `scripts/fetch-status.sh:11` **Vulnerability Type**: Unsafe JSON construction **Risk Level**: Medium ### Vulnerable Code `scripts/fetch-plan.sh:11`: ```bash -d "{\"siteId\":\"${LLMSIGNAL_SITE_ID}\",\"apiKey\":\"${LLMSIGNAL_API_KEY}\",\"persist\":true}" ``` `scripts/fetch-status.sh:11`: ```bash -d "{\"siteId\":\"${LLMSIGNAL_SITE_ID}\",\"apiKey\":\"${LLMSIGNAL_API_KEY}\"}" ``` The corresponding unsafe payload design is also documented in `templates/plan.request.json:1-5`: ```json { "siteId": "${LLMSIGNAL_SITE_ID}", "apiKey": "${LLMSIGNAL_API_KEY}", "persist": true } ``` And in `templates/status.request.json:1-4`: ```json { "siteId": "${LLMSIGNAL_SITE_ID}", "apiKey": "${LLMSIGNAL_API_KEY}" } ``` ### Technical Analysis The scripts build JSON by directly interpolating environment variables into a quoted string. JSON-sensitive characters such as quotation marks, backslashes, and control characters are not escaped. An attacker who can influence `LLMSIGNAL_SITE_ID` or `LLMSIGNAL_API_KEY` can terminate the intended string value and insert additional JSON properties or malformed syntax. This is request-body injection rather than shell-command injection: shell metacharacters inside these variable expansions are not re-evaluated as shell syntax because the expansions remain within a quoted argument. The behavior can nevertheless alter the data submitted to the remote service, exploit duplicate-key parsing differences, or make requests consistently fail. ### Attack Path 1. An attacker gains influence over an environment variable used by the Skill, such as `LLMSIGNAL_SITE_ID`. 2. The attacker supplies a value containing JSON syntax, for example a quotation mark followed by additional properties. 3. The shell interpolates the value without JSON escaping. 4. `curl` sends the manipul ...[truncated 630 chars]
Remediation
## Remediation Suggestions 1. Construct request bodies with a real JSON serializer instead of string interpolation. For example: ```bash payload="$(jq -n \ --arg siteId "$LLMSIGNAL_SITE_ID" \ '{siteId: $siteId, persist: true}')" curl -sS -X POST "$endpoint" \ -H "Content-Type: application/json" \ -H "X-LLMSIGNAL-KEY: ${LLMSIGNAL_API_KEY}" \ --data-binary "$payload" ``` 2. Remove the API key from the JSON body and retain it only in the authentication header. 3. Validate `LLMSIGNAL_SITE_ID` against its documented format and reject unexpected characters or excessive lengths. 4. Add tests covering quotation marks, backslashes, newlines, control characters, empty values, and oversized input. 5. Update both request templates so they no longer encourage direct textual substitution of secrets or unescaped values.

other

Warning
Location
prompts/system.txt:3
Finding
Remote Plan Responses Can Authorize Automatic Agent Actions## Vulnerability Details **File Location**: `prompts/system.txt:3-17`; related policy appears in `SKILL.md:21-24` **Vulnerability Type**: Excessive trust in remote workflow instructions **Risk Level**: Medium ### Vulnerable Code `prompts/system.txt:3-17`: ```text Execution policy: - Always call /api/agent/v1/plan first before recommending actions. - Automatically execute only actions marked automation=auto_safe. - For manual or assist actions, return exact patch/command suggestions for human approval. - Never output or log API keys or secrets. Workflow: 1) Fetch plan with persist=true to store run/action history. 2) Prioritize actions by priority high -> medium -> low. 3) For each action, return: - title - reason - exact steps - command/diff scaffold (if present) 4) After implementation, run status checks and verify outcomes. 5) Re-open actions when verification is negative or confidence is low. ``` `SKILL.md:21-24`: ```text 1. Call `POST /api/agent/v1/plan` before recommending actions. 2. Automatically execute only `auto_safe` actions. 3. Route `manual` and `assist` actions to human approval. 4. Never output API keys or secrets. ``` ### Technical Analysis The remote plan service can provide action content and assign the `auto_safe` classification. The Skill then directs the agent to execute actions carrying that classification automatically. The reviewed package does not specify a strict response schema, cryptographic response verification, local command allowlist, path restrictions, sandbox boundary, or an independent safety decision that cannot be overridden by server-provided data. Consequently, the same remote party that proposes an action can label that action as safe enough to bypass human approval. This issue is amplified by the unrestricted endpoint configuration in the shell scripts. A compromised or attacker-selected endpoint could supply arbitrary action text and ...[truncated 1319 chars]
Remediation
## Remediation Suggestions 1. Treat all remote plan content and safety labels as untrusted data. 2. Require explicit human approval before executing any server-provided command, script, patch, deployment, or production change. 3. If limited automation is essential, define a local allowlist of exact operations, arguments, writable paths, destinations, and resource limits. The remote response must not be able to extend this allowlist. 4. Validate responses against a strict schema and reject unknown fields, malformed classifications, embedded instructions, and free-form executable content. 5. Separate descriptive recommendations from executable operations. Convert approved action types into locally maintained implementations rather than executing server-supplied commands. 6. Run permitted automation in a sandbox with minimal filesystem, environment, credential, and network access. 7. Authenticate the expected endpoint, prohibit arbitrary base URLs, and consider signed responses if plans can authorize consequential actions. 8. Log action identifiers and approval decisions without logging credentials or other sensitive request data.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (7)

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill exposes shell execution capability via referenced scripts but does not declare an explicit tool scope such as permissions or allowed-tools. That makes the operational boundary unclear, increasing the risk that an agent can invoke shell unexpectedly or with broader access than intended, especially in environments that rely on metadata for enforcement or review.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
## Execution policy

1. Call `POST /api/agent/v1/plan` before recommending actions.
2. Automatically execute only `auto_safe` actions.
3. Route `manual` and `assist` actions to human approval.
4. Never output API keys or secrets.
Confidence
90% confidence
Finding
The instruction to automatically execute `auto_safe` actions delegates trust to an external planner's classification without defining local verification criteria. In a skill that fetches and runs externally derived action plans, this creates a real risk of unintended autonomous changes if the remote service misclassifies an action, is compromised, or returns overly broad steps.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
Execution policy:
- Always call /api/agent/v1/plan first before recommending actions.
- Automatically execute only actions marked automation=auto_safe.
- For manual or assist actions, return exact patch/command suggestions for human approval.
- Never output or log API keys or secrets.
Confidence
80% 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.

External Transmission

Medium
Category
Data Exfiltration
Content
: "${LLMSIGNAL_SITE_ID:?Missing LLMSIGNAL_SITE_ID}"
: "${LLMSIGNAL_API_KEY:?Missing LLMSIGNAL_API_KEY}"

curl -sS -X POST "${LLMSIGNAL_BASE_URL%/}/api/agent/v1/plan" \
  -H "Content-Type: application/json" \
  -H "X-LLMSIGNAL-KEY: ${LLMSIGNAL_API_KEY}" \
  -d "{\"siteId\":\"${LLMSIGNAL_SITE_ID}\",\"apiKey\":\"${LLMSIGNAL_API_KEY}\",\"persist\":true}"
Confidence
92% confidence
Finding
The external transmission itself is expected for a workflow-fetching script, but here it carries a sensitive API key to a remote endpoint whose scheme is fully controlled by LLMSIGNAL_BASE_URL. Because the script does not restrict the destination or require TLS, a misconfigured or malicious base URL could cause credentials and site identifiers to be sent to an attacker-controlled or plaintext endpoint.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The script transmits the API key to an external service twice: once in the custom header and again in the JSON body. Including long-lived credentials in request bodies increases the risk of leakage via logs, proxies, monitoring systems, error traces, or downstream storage, and the file provides no enforcement that the destination uses HTTPS or any warning to the operator about credential transmission.

External Transmission

Medium
Category
Data Exfiltration
Content
: "${LLMSIGNAL_SITE_ID:?Missing LLMSIGNAL_SITE_ID}"
: "${LLMSIGNAL_API_KEY:?Missing LLMSIGNAL_API_KEY}"

curl -sS -X POST "${LLMSIGNAL_BASE_URL%/}/api/agent/v1/status" \
  -H "Content-Type: application/json" \
  -H "X-LLMSIGNAL-KEY: ${LLMSIGNAL_API_KEY}" \
  -d "{\"siteId\":\"${LLMSIGNAL_SITE_ID}\",\"apiKey\":\"${LLMSIGNAL_API_KEY}\"}"
Confidence
95% confidence
Finding
This curl invocation performs an external POST using sensitive values from environment variables, including an API key and site ID. External transmission alone can be legitimate, but here it becomes a true vulnerability because the destination is variable, the request includes credentials, and there are no safeguards preventing secret exfiltration or insecure transport. Within a workflow skill designed to run agent actions, this increases risk because secrets may be automatically available and sent without meaningful user review.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The script sends a secret API key to a remote endpoint twice: once in the X-LLMSIGNAL-KEY header and again inside the JSON body, along with a site identifier. Because LLMSIGNAL_BASE_URL is fully caller-controlled and there is no enforcement of HTTPS, hostname allowlisting, or disclosure to the user, the skill can exfiltrate credentials to an arbitrary server and may leak them in transit if HTTP is used. In an agent skill context, this is more dangerous because automation may execute it non-interactively with privileged environment variables already present.

Static analysis

No suspicious patterns detected.