T09 · Insecure Skill Coding Practices
- Location
SKILL.md:72- Finding
Shell Command Injection Through Unsafe Prompt Interpolation
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 72–82. The same unsafe construction pattern is repeated in the examples at lines 128–138, 143–157, 162–172, and 177–189.
Vulnerability Type: Shell command injection and unsafe JSON construction
Risk Level: MediumVulnerable 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-video?async=true" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $OATDA_API_KEY" \ -d '{ "provider": "<PROVIDER>", "model": "<MODEL>", "prompt": "<VIDEO_DESCRIPTION>" }'Technical Analysis
The Skill instructs an agent to insert provider, model, and user-controlled video-description values into a JSON document embedded directly in a single-quoted shell argument. It does not require the use of a JSON encoder or any shell-safe mechanism for passing these values.
If an agent implements the placeholders through direct textual substitution, a single quote in a supplied value can terminate the shell string. Subsequent text can then be interpreted by the shell as operators, arguments, or commands. Double quotes, backslashes, newlines, and control characters can also corrupt the JSON structure or modify the request semantics even when they do not achieve shell execution.
The credential-file access itself is consistent with the declared authenticated OATDA functionality: the Skill reads a dedicated OATDA credential and sends it to the declared HTTPS OATDA endpoint. However, successful command injection would execute in the same process context and could expose that credential. The instruction permitting disclosure of the first eight API-key characters is also unnecessary; key presence should be reported without revealing any portion of the secret ...[truncated 1596 chars]
- Remediation
View remediation
Remediation Suggestions
Require all request bodies to be constructed with a JSON encoder rather than by substituting values into shell source. Pass dynamic values through shell variables and
jq --arg, for example:bash payload=$(jq -n \ --arg provider "$PROVIDER" \ --arg model "$MODEL" \ --arg prompt "$VIDEO_DESCRIPTION" \ '{provider: $provider, model: $model, prompt: $prompt}') curl --fail-with-body -sS \ -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $OATDA_API_KEY" \ --data-binary "$payload" \ "https://oatda.com/api/v1/llm/generate-video?async=true"Apply the same encoding approach to every optional or model-specific parameter. Build nested
model_paramsas structured JSON rather than accepting raw JSON fragments from users.Additionally:
- Explicitly prohibit direct textual replacement of placeholders inside shell commands.
- Validate provider and model values against allowlists or values returned by the model-discovery endpoint.
- Validate parameter types, URL schemes, duration, dimensions, and other bounded values before request construction.
- Use
curl --fail-with-body -sSso transport and HTTP failures are not silently ignored. - Verify only whether the API key exists; do not display its first eight characters or any other portion.
- Restrict
~/.oatda/credentials.jsonto the owning account, preferably with mode0600, and prefer the dedicated environment variable when it is already configured. - Update every example in the Skill to demonstrate the safe construction pattern so an agent is not encouraged to reproduce the vulnerable form.
