T09 · Insecure Skill Coding Practices
- Location
SKILL.md:54- Finding
Authentication Secrets Encouraged in Command-Line Arguments
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill does what it says, but it enables third-party voice cloning without meaningful consent or privacy guardrails for sensitive voice data.
Review before installing. Only use this skill with voices you own or have explicit permission to clone, and assume uploaded audio, submitted text, voice IDs, and API credentials are processed by Volcano Engine/Bytedance. Prefer environment variables over command-line credential flags, avoid sensitive or regulated text unless approved, and be aware that generated audio is downloaded from a provider-returned URL without additional validation.
SKILL.md:54Authentication Secrets Encouraged in Command-Line Arguments
SKILL.md:19Unpinned Third-Party Dependency Installation
scripts/tts.py:188Unvalidated Remote Audio URL and Unbounded Download
The code aligns with the TTS portion of the description: it calls the Volcano Engine/Doubao speech synthesis API, supports configurable synthesis options, and can synthesize using an existing cloned speaker ID. However, it does not implement actual voice cloning or training cloned voices from audio samples. There is no audio upload, dataset handling, training request, or voice creation endpoint interaction. Therefore the description overstates the implemented capabilities, making this a material description-behavior mismatch.
The skill explicitly enables voice cloning from uploaded audio samples but provides no warning or safeguard around consent, impersonation, or privacy. In this context, that omission is dangerous because voice cloning is inherently dual-use and can facilitate fraud, harassment, or non-consensual biometric data processing if users are not clearly constrained and warned.
The skill uses 'env' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.
The skill uses 'network' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def load_dotenv():
"""Load environment variables from a .env file (script directory first, then parent directory). Does not overwrite existing environment variables."""
script_dir = os.path.dirname(os.path.abspath(__file__))
candidates = [
os.path.join(script_dir, ".env"),
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def load_dotenv():
"""Load environment variables from a .env file (script directory first, then parent directory). Does not overwrite existing environment variables."""
script_dir = os.path.dirname(os.path.abspath(__file__))
candidates = [
os.path.join(script_dir, ".env"),
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def load_dotenv():
"""Load environment variables from a .env file (script directory first, then parent directory). Does not overwrite existing environment variables."""
script_dir = os.path.dirname(os.path.abspath(__file__))
candidates = [
os.path.join(script_dir, ".env"),
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def load_dotenv():
"""Load environment variables from a .env file (script directory first, then parent directory). Does not overwrite existing environment variables."""
script_dir = os.path.dirname(os.path.abspath(__file__))
candidates = [
os.path.join(script_dir, ".env"),
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""Load environment variables from a .env file (script directory first, then parent directory). Does not overwrite existing environment variables."""
script_dir = os.path.dirname(os.path.abspath(__file__))
candidates = [
os.path.join(script_dir, ".env"),
os.path.join(script_dir, "..", ".env"),
]
for path in candidates:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""Load environment variables from a .env file (script directory first, then parent directory). Does not overwrite existing environment variables."""
script_dir = os.path.dirname(os.path.abspath(__file__))
candidates = [
os.path.join(script_dir, ".env"),
os.path.join(script_dir, "..", ".env"),
]
for path in candidates:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"""Load environment variables from a .env file (script directory first, then parent directory). Does not overwrite existing environment variables."""
script_dir = os.path.dirname(os.path.abspath(__file__))
candidates = [
os.path.join(script_dir, ".env"),
os.path.join(script_dir, "..", ".env"),
]
for path in candidates:
Searching the parent directory for .env broadens the trust boundary and can unintentionally ingest credentials from an unrelated workspace or repository root. In shared or multi-project environments, this may cause credential confusion or accidental use of the wrong secrets, though it is not active credential exfiltration.
script_dir = os.path.dirname(os.path.abspath(__file__))
candidates = [
os.path.join(script_dir, ".env"),
os.path.join(script_dir, "..", ".env"),
]
for path in candidates:
path = os.path.normpath(path)
The reference explicitly documents voice cloning inputs and training behavior but provides no warning that uploaded audio may contain sensitive biometric identifiers and may require consent, retention controls, and jurisdiction-specific compliance. In a skill designed to enable voice cloning, this omission can normalize unsafe use and increase the chance that users submit third-party voice samples without authorization or adequate privacy protections.
This code transmits base64-encoded user-provided voice samples and related metadata to an external third-party API for voice cloning. Because voice samples are highly sensitive biometric data and may also contain spoken personal information, sending them off-box creates meaningful privacy and consent risk if users are not clearly informed and protected.
body["extra_params"] = extra_params
print(f"\nSubmitting voice cloning training (language: {LANGUAGE_MAP.get(args.language, args.language)})...")
resp = requests.post(BASE_URL + CLONE_PATH, headers=headers, json=body, timeout=60)
if resp.status_code != 200:
try:
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
while True:
time.sleep(args.poll_interval)
headers["X-Api-Request-Id"] = str(uuid.uuid4())
resp = requests.post(BASE_URL + GET_VOICE_PATH, headers=headers, json=body, timeout=30)
if resp.status_code != 200:
print(f"Query failed: HTTP {resp.status_code}, retrying...")
continue
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
while True:
time.sleep(args.poll_interval)
headers["X-Api-Request-Id"] = str(uuid.uuid4())
resp = requests.post(BASE_URL + GET_VOICE_PATH, headers=headers, json=body, timeout=30)
if resp.status_code != 200:
print(f"Query failed: HTTP {resp.status_code}, retrying...")
continue
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
print(f" Format: {args.format} {args.sample_rate}Hz")
print(f" Text length: {len(text)} characters")
resp = requests.post(BASE_URL + SUBMIT_PATH, headers=headers, json=body, timeout=30)
if resp.status_code != 200:
try:
The script sends user-provided text and authentication headers to a third-party TTS provider but does not provide an explicit privacy or data-handling warning at runtime. In a voice-cloning and TTS context, input text may contain sensitive content and the skill context increases risk because users may submit private or regulated material for synthesis.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
while True:
time.sleep(args.poll_interval)
headers["X-Api-Request-Id"] = str(uuid.uuid4())
resp = requests.post(BASE_URL + QUERY_PATH, headers=headers, json=query_body, timeout=30)
if resp.status_code != 200:
print(f"Query failed: HTTP {resp.status_code}, retrying...")
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
while True:
time.sleep(args.poll_interval)
headers["X-Api-Request-Id"] = str(uuid.uuid4())
resp = requests.post(BASE_URL + QUERY_PATH, headers=headers, json=query_body, timeout=30)
if resp.status_code != 200:
print(f"Query failed: HTTP {resp.status_code}, retrying...")
The script downloads from an audio_url returned by a remote API without validating the scheme, host, or content type. If the upstream service is compromised, misconfigured, or attacker-influenced, this creates an SSRF-style trust issue and can cause the client to fetch unexpected content or large files to a local path.
def download_audio(audio_url, output_path):
print(f"\nDownloading audio to: {output_path}")
resp = requests.get(audio_url, timeout=60, stream=True)
if resp.status_code != 200:
print(f"Error: Download failed, HTTP {resp.status_code}", file=sys.stderr)
sys.exit(1)