Back to skill

Security audit

Lyric Flip

Security checks for vulnerabilities and agentic risk

Overview

This skill is not clearly malicious, but it needs review because it sends lyrics to an external service and may automatically generate full songs using unsafe shell examples.

Install only if you are comfortable sending lyric prompts, approved lyrics, and style information to SenseAudio using your API key. Review usage costs and avoid pasting sensitive or private lyrics. The skill should be updated to ask separately before music generation and to build JSON safely instead of direct shell interpolation.

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

Warning
Location
SKILL.md:90
Finding
Unsafe User-Controlled Data Interpolation in Shell and JSON Payloads## Vulnerability Details **File Location**: `SKILL.md`, lines 90–95 and 144–155 **Vulnerability Type**: Shell command injection and malformed JSON generation **Risk Level**: Medium ### Vulnerable Code ```bash LYRICS_RESP=$(curl -s -X POST "https://api.senseaudio.cn/v1/song/lyrics/create" \ -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \ -H "Content-Type: application/json" \ -d "{\"prompt\": \"<PROMPT>\", \"provider\": \"sensesong\"}") TASK_ID=$(echo $LYRICS_RESP | jq -r '.task_id // empty') ``` ```bash SONG_RESP=$(curl -s -X POST "https://api.senseaudio.cn/v1/song/music/create" \ -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"model\": \"sensesong\", \"lyrics\": \"<APPROVED_LYRICS>\", \"title\": \"<new theme + based on original title>\", \"vocal_gender\": \"<f|m>\", \"style\": \"<INFERRED_STYLE>\" }") SONG_TASK=$(echo $SONG_RESP | jq -r '.task_id') ``` ### Technical Analysis The instructions place prompt, lyrics, title, and style placeholders directly inside double-quoted shell arguments used to construct JSON. These values can contain user-controlled content. If an agent implements the documented commands by performing direct textual substitution, shell-sensitive sequences such as command substitutions, quotes, backslashes, or newlines become part of the generated shell source. For example, a value containing a command substitution such as `$(command)` may be evaluated by the shell when inserted directly into the command template. Embedded quotation marks and backslashes can also terminate or alter JSON string values, resulting in malformed payloads or unintended API parameters. The API responses are subsequently processed using unquoted expansions: ```bash echo $LYRICS_RESP echo $SONG_RESP ``` Unquoted expansions are subject to shell word splitting and pathname expansion. Th ...[truncated 1850 chars]
Remediation
## Remediation Suggestions Construct JSON with `jq` rather than interpolating data into shell source: ```bash PAYLOAD=$(jq -n \ --arg prompt "$PROMPT" \ --arg provider "sensesong" \ '{prompt: $prompt, provider: $provider}') LYRICS_RESP=$(curl --fail-with-body --silent --show-error \ -X POST "https://api.senseaudio.cn/v1/song/lyrics/create" \ -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \ -H "Content-Type: application/json" \ --data-binary "$PAYLOAD") ``` Apply the same approach to the music request: ```bash PAYLOAD=$(jq -n \ --arg model "sensesong" \ --arg lyrics "$APPROVED_LYRICS" \ --arg title "$TITLE" \ --arg vocal_gender "$VOCAL_GENDER" \ --arg style "$INFERRED_STYLE" \ '{ model: $model, lyrics: $lyrics, title: $title, vocal_gender: $vocal_gender, style: $style }') ``` Process responses without unquoted expansion: ```bash TASK_ID=$(printf '%s' "$LYRICS_RESP" | jq -r '.task_id // empty') ``` Keep user-controlled content in data variables and never generate executable shell source through raw textual substitution. Validate enumerated fields such as vocal gender, impose reasonable length limits, and reject control characters where they are not required.

T09 · Insecure Skill Coding Practices

Note
Location
SKILL.md:100
Finding
Unbounded API Polling Loops Permit Resource Exhaustion## Vulnerability Details **File Location**: `SKILL.md`, lines 100–106 and 160–167 **Vulnerability Type**: Missing timeout, retry limit, and response validation **Risk Level**: Low ### Vulnerable Code ```bash while true; do POLL=$(curl -s "https://api.senseaudio.cn/v1/song/lyrics/pending/$TASK_ID" \ -H "Authorization: Bearer $SENSEAUDIO_API_KEY") STATUS=$(echo $POLL | jq -r '.status') [ "$STATUS" = "SUCCESS" ] || [ "$STATUS" = "FAILED" ] && break sleep 3 done LYRICS=$(echo $POLL | jq -r '.response.data[0].text') ``` ```bash while true; do POLL=$(curl -s "https://api.senseaudio.cn/v1/song/music/pending/$SONG_TASK" \ -H "Authorization: Bearer $SENSEAUDIO_API_KEY") STATUS=$(echo $POLL | jq -r '.status') [ "$STATUS" = "SUCCESS" ] || [ "$STATUS" = "FAILED" ] && break echo "Composing..." sleep 5 done ``` ### Technical Analysis Both polling procedures use unconditional `while true` loops. They have no overall deadline, maximum attempt count, request timeout, or handling for malformed and unexpected responses. Task identifiers are also not validated before being incorporated into polling URLs. The use of `curl -s` suppresses diagnostic output and does not make HTTP error status codes fail the command. If the service repeatedly returns an HTTP error, invalid JSON, an empty response, or an unrecognized status, `STATUS` will not equal `SUCCESS` or `FAILED`, and the loop will continue indefinitely. ### Attack Path 1. Task creation returns an empty or invalid task identifier, or the remote service becomes unavailable. 2. Alternatively, the polling endpoint continuously returns malformed JSON or a status other than the two recognized terminal states. 3. The loop fails to enter either terminal branch. 4. The agent repeatedly makes authenticated network requests every three or five seconds without a stopping condition. 5. The process remains occupied until manually ...[truncated 605 chars]
Remediation
## Remediation Suggestions Add all of the following safeguards: - Validate that each task identifier is nonempty and matches the expected format before polling. - Set a maximum number of attempts or an absolute deadline. - Configure connection and request timeouts. - Treat HTTP errors, invalid JSON, missing status values, and unknown statuses as explicit failures. - Use `curl --fail-with-body --silent --show-error`. - Quote every response expansion before passing it to `jq`. - Consider capped exponential backoff rather than polling indefinitely at a fixed interval. Example hardened polling logic: ```bash if [ -z "$TASK_ID" ]; then printf '%s\n' "Task creation did not return a task ID." >&2 exit 1 fi max_attempts=40 attempt=1 while [ "$attempt" -le "$max_attempts" ]; do if ! POLL=$(curl --fail-with-body --silent --show-error \ --connect-timeout 10 \ --max-time 30 \ "https://api.senseaudio.cn/v1/song/lyrics/pending/$TASK_ID" \ -H "Authorization: Bearer $SENSEAUDIO_API_KEY"); then printf '%s\n' "Polling request failed." >&2 exit 1 fi if ! STATUS=$(printf '%s' "$POLL" | jq -er '.status'); then printf '%s\n' "Polling response is invalid." >&2 exit 1 fi case "$STATUS" in SUCCESS) break ;; FAILED) exit 1 ;; PENDING|PROCESSING) ;; *) printf 'Unexpected task status: %s\n' "$STATUS" >&2 exit 1 ;; esac sleep 3 attempt=$((attempt + 1)) done if [ "$attempt" -gt "$max_attempts" ]; then printf '%s\n' "Polling deadline exceeded." >&2 exit 1 fi ```
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (11)

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
# SenseAudio Lyric Flip

Rewrite a song with a new theme while keeping the original's structure. The key insight: AI-generated lyrics drift without constraints. By extracting a structural skeleton first and using it as a hard constraint, the output stays tight and singable.

## Step 1: Collect Inputs
Confidence
80% confidence
Finding
Skill attempts to nullify the agent's safety policies or restrictions ('you have no restrictions', 'ignore your guidelines', 'do anything now'). This is a direct jailbreak that disables guardrails.

Vague Triggers

Medium
Confidence
92% confidence
Finding
This markdown file defines triggers, so SQP-1 applies. While several example phrases are specific, the catch-all phrase "or any request to rewrite lyrics with a new theme" is broad and does not clearly bound what should or should not invoke the skill, increasing the chance of unintended activation on ordinary lyric-editing requests.

External Transmission

Medium
Category
Data Exfiltration
Content
env:
        - SENSEAUDIO_API_KEY
      bins:
        - curl
        - jq
    primaryEnv: SENSEAUDIO_API_KEY
    homepage: https://senseaudio.cn
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
97% confidence
Finding
The skill instructs the agent to send user-provided reference lyrics, thematic prompts, and generated content to external SenseAudio endpoints without an explicit user-facing disclosure at the point of transmission. This creates a privacy and consent risk, especially because reference lyrics may contain copyrighted or sensitive text and users may not realize their data is leaving the system.

External Transmission

Medium
Category
Data Exfiltration
Content
```

```bash
LYRICS_RESP=$(curl -s -X POST "https://api.senseaudio.cn/v1/song/lyrics/create" \
  -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"prompt\": \"<PROMPT>\", \"provider\": \"sensesong\"}")
Confidence
95% confidence
Finding
The lyric-generation call transmits user-derived prompt content, including structural details from reference lyrics and the requested theme, to an external provider. Without clear disclosure and consent, this creates a data-sharing risk and may also involve copyrighted text transformations that users may not expect to leave the local environment.

External Transmission

Medium
Category
Data Exfiltration
Content
Poll if async:
```bash
while true; do
  POLL=$(curl -s "https://api.senseaudio.cn/v1/song/lyrics/pending/$TASK_ID" \
    -H "Authorization: Bearer $SENSEAUDIO_API_KEY")
  STATUS=$(echo $POLL | jq -r '.status')
  [ "$STATUS" = "SUCCESS" ] || [ "$STATUS" = "FAILED" ] && break
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
Poll if async:
```bash
while true; do
  POLL=$(curl -s "https://api.senseaudio.cn/v1/song/lyrics/pending/$TASK_ID" \
    -H "Authorization: Bearer $SENSEAUDIO_API_KEY")
  STATUS=$(echo $POLL | jq -r '.status')
  [ "$STATUS" = "SUCCESS" ] || [ "$STATUS" = "FAILED" ] && break
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The skill is presented as a lyric-rewrite tool, but its workflow also generates full songs, audio, cover art, and related metadata. This capability expansion increases data handling and action scope beyond what a user may reasonably expect, creating a transparency and consent problem and raising the risk of unintended external generation actions.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
Adding audio composition to a lyric-focused skill broadens external API use and can trigger cost-incurring or privacy-impacting operations that are not necessary for the stated purpose. Users invoking a rewrite/parody flow may not expect automatic music generation, making this a scope-creep issue with security and trust implications.

External Transmission

Medium
Category
Data Exfiltration
Content
If the user wants to shift the style, use their specified direction instead.

```bash
SONG_RESP=$(curl -s -X POST "https://api.senseaudio.cn/v1/song/music/create" \
  -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
Confidence
96% confidence
Finding
This duplicate finding points to the same music-generation transmission path, which sends user-approved lyrics and style information to an external API. In the context of a lyric-rewrite skill, that broader outbound action is more dangerous because users may not anticipate media generation or third-party processing.

External Transmission

Medium
Category
Data Exfiltration
Content
If the user wants to shift the style, use their specified direction instead.

```bash
SONG_RESP=$(curl -s -X POST "https://api.senseaudio.cn/v1/song/music/create" \
  -H "Authorization: Bearer $SENSEAUDIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
Confidence
96% confidence
Finding
This duplicate finding points to the same music-generation transmission path, which sends user-approved lyrics and style information to an external API. In the context of a lyric-rewrite skill, that broader outbound action is more dangerous because users may not anticipate media generation or third-party processing.

Static analysis

No suspicious patterns detected.