Back to skill

Security audit

OATDA Generate Image

Security checks for vulnerabilities and agentic risk

Overview

The skill is a plausible OATDA image-generation helper, but its documented shell command can turn an image prompt into local shell execution and it sends prompts to an external API with locally loaded credentials.

Review this before installing. It is not evidence of intentional theft, but the documented shell command should be fixed to build JSON with a safe encoder such as jq --arg before use. Only use it when you intend to send the prompt to OATDA, avoid confidential or regulated prompt content, and prefer supplying the API key through a controlled environment variable rather than relying on automatic credential-file fallback.

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

Error
Location
SKILL.md:65
Finding

Shell Command Injection Through Unescaped Image Prompt Substitution

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 65-78
Vulnerability Type: Shell command injection caused by unsafe interpolation into a single-quoted command argument
Risk Level: High

Affected code:

bash
export OATDA_API_KEY="${OATDA_API_KEY:-$(cat ~/.oatda/credentials.json 2>/dev/null | jq -r '.profiles[.defaultProfile].apiKey' 2>/dev/null)}" && \
curl -s -X POST "https://oatda.com/api/v1/llm/generate-image" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OATDA_API_KEY" \
  -d '{
    "provider": "<PROVIDER>",
    "model": "<MODEL>",
    "prompt": "<IMAGE_DESCRIPTION>",
    "size": "1024x1024",
    "quality": "standard",
    "n": 1,
    "numberOfImages": 1
  }'

Technical Analysis

The skill instructs the agent to substitute user-derived image descriptions directly into a JSON document enclosed by shell single quotes. No safe JSON encoder, file-based request body, or shell argument construction mechanism is specified.

If the agent performs literal placeholder substitution, an apostrophe in the image description terminates the shell's single-quoted -d argument. The remaining prompt text is then parsed as shell syntax. Shell metacharacters such as semicolons, command substitutions, redirections, and comments can consequently turn prompt content into commands.

JSON escaping alone is insufficient because shell quoting is evaluated before curl processes the JSON. The value must be encoded without ever being reinterpreted as shell source.

The nearby credential-file access is consistent with authenticating the declared image-generation API and prefers the existing environment variable. It does not, by itself, demonstrate privilege escalation. However, successful command injection would execute after OATDA_API_KEY has been exported and could access that credential and any other data available to the agent process.

Attack

...[truncated 1759 chars]

Remediation
View remediation

Remediation Suggestions

  • Never interpolate user-controlled values into shell program text.
  • Construct the request body with jq --arg, which safely performs JSON encoding while passing input as a separate shell argument:
    bash
    payload="$(
      jq -n \
        --arg provider "$PROVIDER" \
        --arg model "$MODEL" \
        --arg prompt "$IMAGE_DESCRIPTION" \
        '{
          provider: $provider,
          model: $model,
          prompt: $prompt,
          size: "1024x1024",
          quality: "standard",
          n: 1,
          numberOfImages: 1
        }'
    )" || exit 1
    
    curl --fail-with-body --silent --show-error \
      -X POST "https://oatda.com/api/v1/llm/generate-image" \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $OATDA_API_KEY" \
      --data-binary "$payload"
    
  • Pass all dynamic values through environment variables or positional arguments rather than inserting them into a generated command string.
  • Do not use eval, sh -c, or equivalent secondary shell evaluation.
  • Validate provider and model against strict allowlists, while treating the prompt as opaque data with the documented length limit.
  • Stop execution when credential resolution fails or returns null; use restrictive permissions such as 0600 for the credential file.
  • Avoid logging complete commands or authorization headers, and ensure diagnostic output cannot expose the API key.
  • Add regression tests containing apostrophes, command substitutions, semicolons, newlines, backslashes, and Unicode characters, verifying that they remain literal JSON prompt content and never execute locally.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (13)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 10)May include surrounding context.

md
"openclaw":
      {
        "emoji": "🎨",
        "requires": { "bins": ["curl", "jq"], "env": ["OATDA_API_KEY"], "config": ["~/.oatda/credentials.json"] },
        "primaryEnv": "OATDA_API_KEY",
      },
  }

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 130)May include surrounding context.

md
"openclaw":
      {
        "emoji": "🎨",
        "requires": { "bins": ["curl", "jq"], "env": ["OATDA_API_KEY"], "config": ["~/.oatda/credentials.json"] },
        "primaryEnv": "OATDA_API_KEY",
      },
  }

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 149)May include surrounding context.

md
"openclaw":
      {
        "emoji": "🎨",
        "requires": { "bins": ["curl", "jq"], "env": ["OATDA_API_KEY"], "config": ["~/.oatda/credentials.json"] },
        "primaryEnv": "OATDA_API_KEY",
      },
  }

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 165)May include surrounding context.

md
"openclaw":
      {
        "emoji": "🎨",
        "requires": { "bins": ["curl", "jq"], "env": ["OATDA_API_KEY"], "config": ["~/.oatda/credentials.json"] },
        "primaryEnv": "OATDA_API_KEY",
      },
  }

Credential Access

High
Category
Privilege Escalation
Confidence
83% confidence
Finding

The skill reads an API key directly from a local credentials file into an environment variable for inline use. Although intended for legitimate authentication, automated file-based secret resolution increases the blast radius of accidental invocation because the skill can immediately access credentials and send authenticated requests without a separate user approval step.

Content

Scanner excerpt · SKILL.md (reported line 25)May include surrounding context.

All commands need the OATDA API key. Resolve it inline for each exec call:

bash
export OATDA_API_KEY="${OATDA_API_KEY:-$(cat ~/.oatda/credentials.json 2>/dev/null | jq -r '.profiles[.defaultProfile].apiKey' 2>/dev/null)}"

If the key is empty or null, tell the user to get one at https://oatda.com and configure it.

Credential Access

High
Category
Privilege Escalation
Confidence
80% confidence
Finding

This command automatically retrieves a bearer token from a local credentials file and uses it in an authenticated external request. The issue is not direct exfiltration of the key, but automatic secret consumption combined with network access can enable unintended authenticated actions when the skill is triggered too broadly.

Content

Scanner excerpt · SKILL.md (reported line 53)May include surrounding context.

Different models support different parameters (sizes, quality, styles, masks, watermarks, negative prompts, etc.). Query before generating:

bash
export OATDA_API_KEY="${OATDA_API_KEY:-$(cat ~/.oatda/credentials.json 2>/dev/null | jq -r '.profiles[.defaultProfile].apiKey' 2>/dev/null)}" && \
curl -s -X GET "https://oatda.com/api/v1/llm/models?type=image" \
  -H "Authorization: Bearer $OATDA_API_KEY" | jq '.image_models[] | {id, supported_params}'

Credential Access

High
Category
Privilege Escalation
Confidence
84% confidence
Finding

The skill auto-loads an API key from disk immediately before making the image-generation request. In context, this creates a meaningful security concern because local credentials are consumed automatically and then used for third-party transmission, making unintended invocation more impactful.

Content

Scanner excerpt · SKILL.md (reported line 65)May include surrounding context.

CRITICAL: The endpoint is /api/v1/llm/generate-image (NOT /api/v1/llm/image — that's vision analysis).

bash
export OATDA_API_KEY="${OATDA_API_KEY:-$(cat ~/.oatda/credentials.json 2>/dev/null | jq -r '.profiles[.defaultProfile].apiKey' 2>/dev/null)}" && \
curl -s -X POST "https://oatda.com/api/v1/llm/generate-image" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OATDA_API_KEY" \

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger description is very broad and can match generic requests to 'create' or 'generate' images, artwork, designs, or mockups. That increases the chance of unintended invocation, which in this skill leads directly to credential use and transmission of user prompts to an external API without a narrowly scoped match condition.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill description explains image generation behavior but does not prominently warn that user prompts are sent to OATDA's external service. Users may disclose sensitive, proprietary, or regulated content in prompts without understanding that the data leaves the local environment.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This command sends the user-supplied image prompt and parameters to an external endpoint along with a bearer token. External transmission is expected for the feature, but it is still a security-relevant data flow because broad triggering and missing disclosure can cause sensitive data to be exfiltrated to a third party unintentionally.

Content

Scanner excerpt · SKILL.md (reported line 66)May include surrounding context.

bash
export OATDA_API_KEY="${OATDA_API_KEY:-$(cat ~/.oatda/credentials.json 2>/dev/null | jq -r '.profiles[.defaultProfile].apiKey' 2>/dev/null)}" && \
curl -s -X POST "https://oatda.com/api/v1/llm/generate-image" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OATDA_API_KEY" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

The example demonstrates the same external POST flow with prompt data and authorization credentials sent to OATDA. While not inherently malicious, it reinforces a pattern of transmitting user content off-platform without an upfront warning in the skill, which can lead to privacy and compliance issues.

Content

Scanner excerpt · SKILL.md (reported line 131)May include surrounding context.

bash
export OATDA_API_KEY="${OATDA_API_KEY:-$(cat ~/.oatda/credentials.json 2>/dev/null | jq -r '.profiles[.defaultProfile].apiKey' 2>/dev/null)}" && \
curl -s -X POST "https://oatda.com/api/v1/llm/generate-image" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OATDA_API_KEY" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

This example also transmits user prompt content externally for image generation. In context, the risk is not code execution but unintended disclosure of user data and routine use of remote services without explicit user awareness.

Content

Scanner excerpt · SKILL.md (reported line 150)May include surrounding context.

bash
export OATDA_API_KEY="${OATDA_API_KEY:-$(cat ~/.oatda/credentials.json 2>/dev/null | jq -r '.profiles[.defaultProfile].apiKey' 2>/dev/null)}" && \
curl -s -X POST "https://oatda.com/api/v1/llm/generate-image" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OATDA_API_KEY" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
93% confidence
Finding

This example sends prompts and model parameters to OATDA's remote API, again creating a privacy and data-governance exposure. The danger is amplified by the skill's broad activation conditions because users may trigger it in contexts where they did not intend third-party transmission.

Content

Scanner excerpt · SKILL.md (reported line 166)May include surrounding context.

bash
export OATDA_API_KEY="${OATDA_API_KEY:-$(cat ~/.oatda/credentials.json 2>/dev/null | jq -r '.profiles[.defaultProfile].apiKey' 2>/dev/null)}" && \
curl -s -X POST "https://oatda.com/api/v1/llm/generate-image" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OATDA_API_KEY" \
  -d '{

Static analysis

No suspicious patterns detected.