T09 · Insecure Skill Coding Practices
- Location
scripts/gen_visuals.sh:72- Finding
Arbitrary Python Code Execution Through Visual Generation Arguments
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is meant to make AI music videos, but unsafe script argument handling could let crafted inputs run local code.
Review carefully before installing. Use it only in a constrained workspace with non-sensitive prompts and limited API keys, confirm each paid generation step, avoid passing untrusted text into script options, and consider fixing the python3 -c interpolation issues before running it with real credentials.
scripts/gen_visuals.sh:72Arbitrary Python Code Execution Through Visual Generation Arguments
scripts/suno_music.sh:123Arbitrary Python Code Execution Through Music and Persona Arguments
scripts/suno_music.sh:79Dry-Run Mode Performs an Unexpected Authenticated Network Request
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
'width': 1536, 'height': 1024
}, ensure_ascii=False))
" > "$body_file"
resp=$(curl -s -X POST "https://api.together.xyz/v1/images/generations" \
-H "Authorization: Bearer $TOGETHER_API_KEY" \
-H "Content-Type: application/json" \
-d @"$body_file")
Although labeled as script fetching, the real issue is unvalidated remote content download from a URL supplied by an external service. This creates a trust-boundary problem where compromised API output could cause arbitrary remote retrieval and storage, which is more dangerous in an automation context that may run in CI or on hosts with network reachability.
if [[ -z "$url" || "$url" == ERROR* ]]; then
echo " ❌ Image gen failed" >&2; return 1
fi
curl -s -o "$outpath" "$url"
echo " ✅ $(basename "$outpath")"
}
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
echo " ❌ Video timeout" >&2; return 1
fi
local poll
poll=$(curl -s "https://api.together.xyz/v2/videos/${video_id}" \
-H "Authorization: Bearer $TOGETHER_API_KEY")
status=$(echo "$poll" | python3 -c "import sys,json; print(json.load(sys.stdin).get('status','unknown'))" 2>/dev/null)
echo " [${attempts}] $status"
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
# Check credits (may not be supported by all sunoapi instances)
echo "🔍 Checking Suno credits..."
CREDITS_RESP=$(curl -s -H "$AUTH" "${API_BASE}/get-credits" 2>/dev/null)
CREDITS=$(echo "$CREDITS_RESP" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('data',0))" 2>/dev/null || echo "unknown")
if [[ "$CREDITS" == "unknown" || "$CREDITS" == "0" ]]; then
CREDITS="N/A (credit API not available)"
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
echo ""
echo "🎵 Generating music..."
GEN_RESP=$(curl -s -X POST "${API_BASE}/generate" \
-H "$AUTH" -H "$CT" \
-d "$BODY")
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
fi
sleep 15
POLL_RESP=$(curl -s -H "$AUTH" "${API_BASE}/generate/record-info?taskId=${TASK_ID}")
STATUS=$(echo "$POLL_RESP" | python3 -c "
import sys, json
d = json.load(sys.stdin)
The lyrics response is embedded into a Python command via shell substitution inside a quoted -c string. Although the code tries to escape single quotes, adversarial API content can still make this fragile and may lead to command or parser breakage, turning untrusted remote data into part of executable interpreter input.
import json
print(json.dumps({'taskId': '$TASK_ID', 'audioId': '$AUDIO_ID'}))
")
LYRICS_RESP=$(curl -s -X POST "${API_BASE}/generate/get-timestamped-lyrics" \
-H "$AUTH" -H "$CT" \
-d "$LYRICS_BODY")
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
'callBackUrl': 'https://localhost/noop',
}))
")
MV_RESP=$(curl -s -X POST "${API_BASE}/mp4/generate" \
-H "$AUTH" -H "$CT" \
-d "$MV_BODY")
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
fi
sleep 20
MV_POLL=$(curl -s -H "$AUTH" "${API_BASE}/mp4/record-info?taskId=${MV_TASK_ID}")
MV_STATUS=$(echo "$MV_POLL" | python3 -c "import sys,json; print(json.load(sys.stdin).get('data',{}).get('successFlag','PENDING'))" 2>/dev/null || echo "PENDING")
MV_VIDEO_URL=$(echo "$MV_POLL" | python3 -c "
import sys, json
User-controlled values derived from TITLE, PROMPT, STYLE, PERSONA_NAME, and PERSONA_DESC are interpolated directly into a python3 -c string using triple-quoted literals. A crafted value containing quote sequences can break out of the Python string and inject arbitrary Python code, leading to local code execution under the script's privileges.
print(json.dumps(body, ensure_ascii=False))
" > "$PERSONA_BODY_FILE"
PERSONA_RESP=$(curl -s -X POST "${API_BASE}/generate/generate-persona" \
-H "$AUTH" -H "$CT" \
-d @"$PERSONA_BODY_FILE")
rm -f "$PERSONA_BODY_FILE"
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.
@pytest.fixture(scope="session")
def skill_env():
"""Environment with API keys from environment variables."""
return os.environ.copy()
@pytest.fixture
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.
@pytest.fixture(scope="session")
def skill_env():
"""Environment with API keys from environment variables."""
return os.environ.copy()
@pytest.fixture
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
img_dir = os.path.join(work_dir, "images")
os.makedirs(img_dir, exist_ok=True)
for i in range(3):
os.system(
f'ffmpeg -y -f lavfi -i color=c=blue:s=1024x1024:d=1 '
f'"{img_dir}/scene_{i:03d}.png" 2>/dev/null'
)
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
img_dir = os.path.join(work_dir, "images")
os.makedirs(img_dir, exist_ok=True)
for i in range(3):
os.system(
f'ffmpeg -y -f lavfi -i color=c=blue:s=1024x1024:d=1 '
f'"{img_dir}/scene_{i:03d}.png" 2>/dev/null'
)
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
)
img_dir = os.path.join(work_dir, "images")
os.makedirs(img_dir, exist_ok=True)
os.system(
f'ffmpeg -y -f lavfi -i color=c=blue:s=1024x1024:d=1 '
f'"{img_dir}/scene_000.png" 2>/dev/null'
)
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
"""
# Arrange: create synthetic audio (10s silence)
audio_path = os.path.join(work_dir, "test_audio.mp3")
os.system(
f'ffmpeg -y -f lavfi -i anullsrc=r=44100:cl=stereo -t 10 '
f'-q:a 9 "{audio_path}" 2>/dev/null'
)
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
"""
# Arrange: create synthetic audio (10s silence)
audio_path = os.path.join(work_dir, "test_audio.mp3")
os.system(
f'ffmpeg -y -f lavfi -i anullsrc=r=44100:cl=stereo -t 10 '
f'-q:a 9 "{audio_path}" 2>/dev/null'
)
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
"""
# Arrange: create synthetic audio (10s silence)
audio_path = os.path.join(work_dir, "test_audio.mp3")
os.system(
f'ffmpeg -y -f lavfi -i anullsrc=r=44100:cl=stereo -t 10 '
f'-q:a 9 "{audio_path}" 2>/dev/null'
)
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
"""
# Arrange: create synthetic audio (10s silence)
audio_path = os.path.join(work_dir, "test_audio.mp3")
os.system(
f'ffmpeg -y -f lavfi -i anullsrc=r=44100:cl=stereo -t 10 '
f'-q:a 9 "{audio_path}" 2>/dev/null'
)
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
colors = ["red", "green", "blue"]
for i, color in enumerate(colors):
img_path = os.path.join(img_dir, f"scene_{i:03d}.png")
os.system(
f'ffmpeg -y -f lavfi -i color=c={color}:s=1024x1024:d=1 '
f'-frames:v 1 "{img_path}" 2>/dev/null'
)
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
"""Assemble slideshow with crossfade transitions."""
# Arrange
audio_path = os.path.join(work_dir, "audio.mp3")
os.system(
f'ffmpeg -y -f lavfi -i "sine=f=440:d=12" '
f'-q:a 9 "{audio_path}" 2>/dev/null'
)
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.
os.makedirs(img_dir, exist_ok=True)
for i in range(3):
img_path = os.path.join(img_dir, f"scene_{i:03d}.png")
os.system(
f'ffmpeg -y -f lavfi -i color=c=0x{i*80:02x}{i*40:02x}FF:s=1920x1080:d=1 '
f'-frames:v 1 "{img_path}" 2>/dev/null'
)
The skill documentation declares required binaries and environment variables and clearly instructs running shell scripts that perform network access, file reads/writes, and media assembly, but it does not declare an explicit tool scope such as permissions or allowed-tools. This creates an authorization ambiguity where an agent platform may expose broader capabilities than users expect, increasing the risk of unintended command execution, filesystem access, or outbound requests.
The Quick Start examples are broad natural-language triggers for expensive, networked generation actions and do not define clear activation boundaries, confirmation requirements, or exclusions. In an agent setting, ambiguous triggers can cause the skill to activate unintentionally, leading to unreviewed API usage, third-party data transmission, and unexpected spending.
The documentation instructs users to provide API keys and describes callback behavior and third-party providers, but it lacks a prominent user-facing warning that prompts, lyrics, generated media, and callback metadata may be transmitted to external services. This can lead users to unknowingly send potentially sensitive creative content or metadata off-platform without informed consent.
No suspicious patterns detected.