Back to skill

Security audit

Feishu Voice Clone TTS Skill

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims, but it can send voice content and a TTS API key to an undocumented, environment-controlled endpoint before posting audio into Feishu.

Review this skill before installing. It needs Feishu and Volcengine credentials and will send your text to TTS infrastructure, upload the generated audio to Feishu, and post it to the configured recipient. Do not use it for secrets or regulated data. Only run it in an environment where VOLC_TTS_URL cannot be set by untrusted parties, or remove/validate that override first; also ensure any cloned voice is used with consent.

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

Warning
Location
feishu_tts.py:20
Finding

Unrestricted TTS Endpoint Override Can Disclose API Credentials and Message Content

Content
View full analysis

Vulnerability Details

File Location: feishu_tts.py:20 and feishu_tts.py:74-79
Vulnerability Type: Arbitrary network destination for sensitive data
Risk Level: Medium

Vulnerable Code

python
VOLC_API_KEY = os.environ.get('VOLC_API_KEY')
VOLC_TTS_URL = os.environ.get('VOLC_TTS_URL', 'https://openspeech.bytedance.com/api/v1/tts')
VOICE_TYPE = os.environ.get('VOLC_VOICE_TYPE')
python
headers = {
    "x-api-key": api_key,
    "Content-Type": "application/json"
}

print(f"Generating voice for: {text}")
response = requests.post(VOLC_TTS_URL, headers=headers, json=payload, timeout=60)

Technical Analysis

The VOLC_TTS_URL environment variable can replace the official Volcengine TTS endpoint with an arbitrary URL. The value is used directly by requests.post without validating its scheme, hostname, port, or destination.

The outbound request contains two sensitive values:

  • The Volcengine API key in the x-api-key header.
  • The complete user-supplied message text in the JSON request body.

The API key may originate from either VOLC_API_KEY or the local ~/.volcengine_key file. Consequently, an attacker who can influence the process environment could redirect a credential loaded from the local configuration file without needing to read that file directly.

Sending the API key and message text to the official Volcengine service is necessary for the declared TTS functionality. Allowing an unrestricted and undocumented destination override is not necessary and exceeds the minimum network privileges required by the Skill.

Attack Path

  1. An attacker or compromised launcher gains the ability to define environment variables for the Skill process.
  2. The attacker sets VOLC_TTS_URL to an HTTPS endpoint under their control.
  3. A user invokes feishu_tts.py with text intended for speech synthesis.
  4. The script retrieves the Volcengine API key from VOLC_API_KEY or ...[truncated 820 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the VOLC_TTS_URL override if custom TTS endpoints are not a required feature, and use a constant official endpoint:

    python
    VOLC_TTS_URL = "https://openspeech.bytedance.com/api/v1/tts"
    
  2. If endpoint configurability is required, parse the URL and enforce an explicit allowlist:

    • Require the https scheme.
    • Require the exact approved hostname, such as openspeech.bytedance.com.
    • Reject embedded credentials, unexpected ports, IP-literal hosts, fragments, and unapproved subdomains.
    • Do not rely on suffix-only hostname checks.
  3. Disable automatic redirects for requests carrying credentials, or validate every redirect destination before following it:

    python
    response = requests.post(
        VOLC_TTS_URL,
        headers=headers,
        json=payload,
        timeout=60,
        allow_redirects=False,
    )
    
  4. Fail closed when endpoint validation fails and avoid sending either the API key or message text until validation is complete.

  5. Document every supported network destination and configuration override so operators can assess data disclosure boundaries.

  6. Use a narrowly scoped Volcengine credential restricted to only the required TTS operation, with quota limits, rotation procedures, and monitoring for anomalous usage.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (20)

Tainted flow: 'VOLC_TTS_URL' from os.environ.get (line 22, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The destination URL for TTS is taken from the VOLC_TTS_URL environment variable and used directly in requests.post while sending user-provided text and an API key header. If that environment variable is modified, the skill can exfiltrate sensitive message content and credentials to an attacker-controlled endpoint.

Content

Scanner excerpt · feishu_tts.py (reported line 80)May include surrounding context.

python
}

    print(f"Generating voice for: {text}")
    response = requests.post(VOLC_TTS_URL, headers=headers, json=payload, timeout=60)

    if response.ok:
        result = response.json()

Tainted flow: 'headers' from os.environ.get (line 74, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · feishu_tts.py (reported line 110)May include surrounding context.

python
"app_id": FEISHU_APP_ID,
        "app_secret": FEISHU_APP_SECRET
    }
    resp = requests.post(url, headers=headers, json=data, timeout=30)
    result = resp.json()
    if result.get('code') != 0:
        print(f"Error getting token: {result}")

Tainted flow: 'headers' from os.environ.get (line 74, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · feishu_tts.py (reported line 147)May include surrounding context.

python
with open(opus_path, 'rb') as f:
        files = {'file': ('audio.opus', f, 'audio/opus')}
        data = {'file_type': 'opus', 'file_name': 'voice.opus', 'duration': str(duration_ms)}
        resp = requests.post(url, headers=headers, files=files, data=data, timeout=60)

    result = resp.json()
    if result.get('code') != 0:

Tainted flow: 'headers' from os.environ.get (line 74, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · feishu_tts.py (reported line 188)May include surrounding context.

python
"msg_type": "audio",
        "content": json.dumps({"file_key": file_key})
    }
    resp = requests.post(url, headers=headers, params=params, json=data, timeout=30)
    return resp.json()

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 · feishu_tts.py (reported line 99)May include surrounding context.

python
def get_tenant_access_token():
    """获取飞书 tenant access token"""
    if not FEISHU_APP_ID or not FEISHU_APP_SECRET:
        print("Error: FEISHU_APP_ID or FEISHU_APP_SECRET not set")
        sys.exit(1)

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 · feishu_tts.py (reported line 234)May include surrounding context.

python
def get_tenant_access_token():
    """获取飞书 tenant access token"""
    if not FEISHU_APP_ID or not FEISHU_APP_SECRET:
        print("Error: FEISHU_APP_ID or FEISHU_APP_SECRET not set")
        sys.exit(1)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill sends user-provided text and generated audio to external systems including Volcengine TTS and Feishu, but the README does not clearly disclose this data flow. Users may unknowingly transmit sensitive content to third parties and into chats, creating privacy, confidentiality, and accidental data-sharing risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README describes cloning and using a person's voice but does not warn about consent, impersonation, or privacy risks. In a voice-cloning skill, omission of these safeguards can normalize misuse and increase the chance of non-consensual voice replication or deceptive messaging.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill documentation instructs users to send arbitrary text to a third-party TTS provider and then into Feishu, but it does not warn that user-provided content will leave the local environment and be transmitted to external services. This creates a real privacy and data-handling risk because users may provide sensitive text without understanding it will be shared with Volcengine and posted into chats.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

User-facing descriptions and usage strings are written in Chinese, and the script instructs users with Chinese-only prompts such as the text input examples. There is no indication that the locale restriction is optional, user-selected, or justified as a region-specific tool.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · feishu_tts.py (reported line 46)May include surrounding context.

python
api_key = get_volc_api_key()
    if not api_key:
        print("Error: VOLC_API_KEY not set and no config file found")
        print("Please set VOLC_API_KEY environment variable or create ~/.volcengine_key")
        sys.exit(1)

    voice_type = VOICE_TYPE

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This is an external transmission of user text and an API key to a URL that can be overridden via environment variable, making the transmission materially risky. In this skill's context, the feature is expected, but the controllable destination significantly increases the chance of silent exfiltration.

Content

Scanner excerpt · feishu_tts.py (reported line 80)May include surrounding context.

python
}

    print(f"Generating voice for: {text}")
    response = requests.post(VOLC_TTS_URL, headers=headers, json=payload, timeout=60)

    if response.ok:
        result = response.json()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill sends user-supplied text to an external TTS provider without any explicit disclosure or confirmation at runtime. In a messaging/voice skill, this creates a privacy risk because sensitive content may be transmitted off-system to a third party unexpectedly.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · feishu_tts.py (reported line 110)May include surrounding context.

python
"app_id": FEISHU_APP_ID,
        "app_secret": FEISHU_APP_SECRET
    }
    resp = requests.post(url, headers=headers, json=data, timeout=30)
    result = resp.json()
    if result.get('code') != 0:
        print(f"Error getting token: {result}")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · feishu_tts.py (reported line 125)May include surrounding context.

python
"-c:a", "libopus", "-b:a", "24k",
        output_path
    ]
    subprocess.run(cmd, check=True, capture_output=True)
    return output_path

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · feishu_tts.py (reported line 133)May include surrounding context.

python
"""获取音频时长(毫秒)"""
    cmd = ["ffprobe", "-v", "error", "-show_entries", "format=duration",
           "-of", "default=noprint_wrappers=1:nokey=1", opus_path]
    result = subprocess.run(cmd, capture_output=True, text=True)
    return int(float(result.stdout.strip()) * 1000)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The generated voice file is uploaded and then sent into Feishu chats without any explicit confirmation that recipients will receive the content. This can lead to accidental disclosure if the configured chat ID is wrong or if the operator does not realize the message is being distributed to others.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · feishu_tts.py (reported line 188)May include surrounding context.

python
"msg_type": "audio",
        "content": json.dumps({"file_key": file_key})
    }
    resp = requests.post(url, headers=headers, params=params, json=data, timeout=30)
    return resp.json()

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The natural-language instructions in the README are entirely in Chinese, and there is no indication that the skill is region-specific or that users may choose another language. Under the policy rule, forcing a specific language without opt-in can be a locale policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The natural-language instructions and usage examples are presented exclusively in Chinese, which can impose a language requirement on users without opt-in. The policy guidance says to flag skills that force a specific language unless the constraint is explicitly offered as a choice or clearly justified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.