Back to skill

Security audit

acestep

Security checks for vulnerabilities and agentic risk

Overview

This is a legitimate ACE-Step music API wrapper, but its shell helper has credential-display and output-path flaws that should be reviewed before installation.

Install only if you trust the ACE-Step endpoint and are comfortable reviewing or patching the helper script first. Avoid running plain config or config --get api_key, keep API keys out of shared logs, and validate job IDs/output filenames before using custom or remote API servers.

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
scripts/acestep.sh:287
Finding
Plaintext API Key Disclosure Through the Default Configuration Command<![CDATA[ ## Vulnerability Details **File Location**: `scripts/acestep.sh`, lines 287-292 **Vulnerability Type**: Sensitive credential exposure **Risk Level**: Medium ### Vulnerable Code ```bash *) echo "Config file: $CONFIG_FILE" echo "Output dir: $OUTPUT_DIR" echo "----------------------------------------" cat "$CONFIG_FILE" echo "----------------------------------------" ``` ### Technical Analysis The default branch of `cmd_config` prints the configuration file without masking sensitive fields. Because `config.json` stores `api_key` as plaintext, invoking `acestep.sh config` without an explicit action discloses the complete credential. This behavior is inconsistent with the safer `config --list` implementation, which masks populated API keys before displaying the configuration. It also contradicts the guidance in `SKILL.md`, which says that API keys must not be printed and recommends `config --check-key`. The disclosure does not require bypassing file permissions: it occurs through an ordinary documented command path and can therefore be triggered accidentally by a user, an AI agent, an automation script, or a troubleshooting workflow. ### Attack Path 1. A user configures a valid API key using `config --set api_key`. 2. The key is stored in `scripts/config.json`. 3. A user or agent invokes `./scripts/acestep.sh config` without `--list`, `--get`, or another action. 4. The default branch executes `cat "$CONFIG_FILE"`. 5. The plaintext key is written to standard output. 6. The credential may be retained in an AI transcript, CI log, terminal history capture, support record, or screen recording accessible to another party. ### Impact Assessment An attacker who gains access to the exposed output may obtain the privileges associated with the API key. Depending on the remote service's authorization model, this could permit unauthorized music-generation requests, consumption of account quota ...[truncated 299 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the raw `cat "$CONFIG_FILE"` call with the same masking filter used by `config --list`: ```bash jq 'walk( if type == "object" and has("api_key") and (.api_key | length) > 0 then .api_key = "***" else . end )' "$CONFIG_FILE" ``` 2. Make `config --list` the default behavior instead of maintaining a separate, unsafe display path. 3. Explicitly reject `config --get api_key`; direct users to `config --check-key`. 4. Prefer reading the API key from an environment variable or operating-system credential store rather than persisting it in project-local plaintext. 5. If file-based storage remains necessary, create `config.json` with restrictive permissions, such as mode `0600`, and verify ownership before reading it. 6. Add regression tests confirming that no invocation of the configuration command emits a configured API key. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/acestep.sh:214
Finding
Arbitrary File Write Through Unsanitized Server-Controlled Job Identifiers<![CDATA[ ## Vulnerability Details **File Location**: `scripts/acestep.sh`, lines 214-221 **Vulnerability Type**: Path traversal and arbitrary file overwrite **Risk Level**: High ### Vulnerable Code ```bash save_result() { local job_id="$1" local result_json="$2" ensure_output_dir local output_file="${OUTPUT_DIR}/${job_id}.json" echo "$result_json" > "$output_file" echo -e "${GREEN}Result saved: $output_file${NC}" } ``` The affected identifier can originate from a remote completion response: ```bash # Generate a job_id from the completion id local job_id job_id=$(jq -r '.id // empty' "$resp_file" 2>/dev/null) [ -z "$job_id" ] && job_id="completion-$(date +%s)" ``` The same identifier is also used when constructing audio output paths: ```bash local output_file="${OUTPUT_DIR}/${job_id}_${count}.${audio_format}" ``` ```bash local output_file="${OUTPUT_DIR}/${job_id}_$((i+1)).${audio_format}" ``` ### Technical Analysis The script assumes that `job_id` is a safe filename component. It concatenates the value directly into paths used by shell redirection and `curl -o`, without validation, canonicalization, or containment checks. In completion mode, the identifier is taken from the remote API's JSON response. Because the API endpoint is configurable, a malicious or compromised service can return an identifier containing path traversal sequences such as `../../directory/target`. Shell quoting prevents command injection but does not neutralize filesystem traversal. The operating system resolves `..` components before opening the destination file. The native `status` command also accepts a caller-provided job identifier, extending the unsafe path construction to locally supplied values. Existing files are not protected against replacement: shell redirection truncates matching files, and `curl -o` writes to the selected destination. ### Attack Path 1. The victim configures or is induced to configure an attacker-controlled or compromised ...[truncated 1826 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate every job identifier before any filesystem use. Apply a strict allowlist, for example: ```bash validate_job_id() { local job_id="$1" [[ "$job_id" =~ ^[A-Za-z0-9_-]+$ ]] || { echo "Error: invalid job identifier" >&2 return 1 } } ``` 2. Prefer generating a local random filename independent of any server-controlled identifier. Store the remote identifier only inside metadata. 3. Canonicalize the final parent directory and verify that it remains under the canonical `OUTPUT_DIR` before opening the file. 4. Reject identifiers containing `/`, `\`, `..`, control characters, leading dots, or empty values. 5. Validate `generation.audio_format` against a fixed set such as `mp3`, `wav`, and `flac` before using it as a filename suffix. 6. Use no-clobber or exclusive file creation where overwriting existing files is not required. 7. Apply the validation consistently in `save_result`, `download_audios`, `parse_completion_response`, `cmd_status`, and every other path-building location rather than relying only on upstream callers. 8. Add tests using identifiers such as `../target`, `../../target`, absolute paths, backslash-based traversal, encoded separators, and control characters, and verify that no file is created outside `acestep_output`. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (13)

Vague Triggers

Medium
Confidence
95% confidence
Finding
The manifest description says to use the skill when users mention 'generating music, creating songs, music production, remix, or audio continuation.' Several of these phrases, especially 'creating songs' and 'music production,' are broad and lack explicit scope or exclusion conditions, which could cause unintended invocation in general conversation.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The configuration sets `generation.vocal_language` to `en`, and the documentation presents this as the default behavior without stating that the user should choose or confirm the language. This can violate language/locale policy when the user has not requested English vocals or been offered a language choice.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
If jq is not installed, the script will attempt to install it automatically. If automatic installation fails:
- **Windows**: `choco install jq` or download from https://jqlang.github.io/jq/download/
- **macOS**: `brew install jq`
- **Linux**: `sudo apt-get install jq` (Debian/Ubuntu) or `sudo dnf install jq` (Fedora)

### Before First Use
Confidence
89% confidence
Finding
The skill instructs installation of jq using privileged package-manager commands and also states the script may attempt automatic installation. In an agentic context, this expands from music generation into system modification with elevated privileges, creating risk of unauthorized changes, abuse of sudo-capable environments, or unsafe dependency installation paths if followed automatically.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The manifest describes a skill for generating and editing music via the ACE-Step API, but the config command can print arbitrary configuration values directly, including `api_key` if the user runs `config --get api_key`. That capability is not necessary to perform music generation itself and exposes stored credentials in plaintext as part of normal skill behavior.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The default `config` action prints the entire raw configuration file with `cat "$CONFIG_FILE"`, which includes the stored API key in plaintext. This creates an unnecessary secret exposure path for a music-generation tool and can leak credentials into terminal scrollback, logs, screen recordings, or agent-captured output.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The configuration display path exposes stored credentials without any warning or confirmation. In an agent or shared-shell context, this is more dangerous because command output may be captured automatically, turning a local convenience command into a credential disclosure vector.

External Transmission

Medium
Category
Data Exfiltration
Content
echo "Available Models:"
    echo "----------------------------------------"
    if [ -n "$api_key" ]; then
        curl -s -H "Authorization: Bearer ${api_key}" "${api_url}/v1/models"
    else
        curl -s "${api_url}/v1/models"
    fi
Confidence
70% 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
local http_code
    if [ -n "$api_key" ]; then
        http_code=$(curl -s -w "%{http_code}" --connect-timeout 10 --max-time 660 \
            -o "$resp_file" \
            -X POST "${api_url}/v1/chat/completions" \
            -H "Content-Type: application/json; charset=utf-8" \
Confidence
70% 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
local api_key=$(load_api_key)
        local response
        if [ -n "$api_key" ]; then
            response=$(curl -s -X POST "${api_url}/release_task" \
                -H "Content-Type: application/json; charset=utf-8" \
                -H "Authorization: Bearer ${api_key}" \
                --data-binary "@${temp_payload}")
Confidence
70% 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
local api_key=$(load_api_key)
        local response
        if [ -n "$api_key" ]; then
            response=$(curl -s -X POST "${api_url}/release_task" \
                -H "Content-Type: application/json; charset=utf-8" \
                -H "Authorization: Bearer ${api_key}" \
                --data-binary "@${temp_payload}")
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Context-Inappropriate Capability

Low
Confidence
80% confidence
Finding
The manifest describes a skill for generating and editing music via the ACE-Step API, but it explicitly allows the Bash tool. Later documentation also states the script may attempt to install `jq` automatically, introducing system-modifying command execution that is not clearly justified by the music-creation purpose itself.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The script sets `LANG` and `LC_ALL` to `en_US.UTF-8` when they are unset, which imposes a specific locale choice in natural-language behavior. This is a language/locale policy concern because the user is not offered a choice or explicit opt-in, and the locale is not justified as region-specific.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The config sets "vocal_language" to "en", which imposes a specific language choice in a natural-language-facing setting. The file does not indicate that this is optional, user-selectable, or justified as a region-specific constraint.

Static analysis

No suspicious patterns detected.