T09 · Insecure Skill Coding Practices
- Location
scripts/run_interview.py:305- Finding
Excessive Persistence of Raw ASR Provider Responses
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a coherent Chinese voice interview simulator, but users should understand that it sends interview audio and generated text to configured cloud AI services and saves reports locally.
Install only if you are comfortable sharing interview audio, transcripts, prompts, and summaries with the configured LLM/ASR/TTS providers. Use private output locations, avoid sensitive personal details in practice answers, consider --no-tts when voice playback is not needed, and prefer pinned dependency versions and deletion of saved reports/audio after use.
scripts/run_interview.py:305Excessive Persistence of Raw ASR Provider Responses
scripts/run_interview.py:160Prompt Injection Through Untrusted Candidate Answers and Interview History
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
data["language"] = language.replace("-CN", "").lower()
with audio_path.open("rb") as handle:
files = {"file": (audio_path.name, handle)}
response = requests.post(
ASR_URL,
headers=headers,
data=data,
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
"voice_setting": {"voice_id": TTS_VOICE_ID},
"audio_setting": {"format": "mp3", "sample_rate": 32000},
}
response = requests.post(TTS_URL, headers=headers, json=payload, timeout=TTS_TIMEOUT)
response.raise_for_status()
result = response.json()
if result.get("base_resp", {}).get("status_code") != 0:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def load_env() -> None:
if load_dotenv is None:
return
for path in (SKILL_DIR / ".env", Path.cwd() / ".env"):
if path.exists():
load_dotenv(path)
The skill describes executable behavior that uses environment variables, networked LLM/ASR/TTS services, and writes outputs to disk, but it does not declare any explicit tool scope or permissions. This creates a trust and containment gap: a host may expose broader capabilities than intended, and reviewers or runtime policy engines cannot clearly enforce least privilege for a skill that handles user audio, transcripts, and generated reports.
The description states the skill performs a Chinese voice interview simulation and later specifies a default language of zh-CN, while the scope explicitly excludes English interviews. This imposes a language constraint as a policy-relevant natural-language behavior without presenting it as a user choice or opt-in.
The prompt explicitly constrains the interaction language to Chinese using natural-language instructions, including a fixed 语言:中文 field. This appears to enforce a specific language/locale choice rather than offering user selection or documenting a region-specific justification, which matches the policy-violation criteria.
The module instructions repeatedly specify that the simulated interview and generated content must be in Chinese, reinforcing a fixed language policy across the skill. Because the file does not indicate user opt-in or a justified locale restriction, this is a natural-language policy concern.
The example SessionConfig sets "language": "zh-CN", which natural-language-wise implies the skill operates in a fixed locale. The file does not mention any user-selectable language option or justify that the skill is intentionally region-specific, so this can conflict with language/locale choice policy.
Multiple system prompts explicitly instruct the model to act as a Chinese interviewer and produce Chinese interview content, which enforces a locale/language constraint at the skill level. Although a --language flag exists later, these prompts still hard-code Chinese behavior rather than offering a genuine user language choice.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
LLM_TIMEOUT = float(os.environ.get("INTERVIEW_LLM_TIMEOUT", "60"))
LLM_TEMPERATURE = float(os.environ.get("INTERVIEW_LLM_TEMPERATURE", "0.3"))
ASR_URL = os.environ.get("INTERVIEW_ASR_URL", "https://api.senseaudio.cn/v1/audio/transcriptions")
ASR_MODEL = os.environ.get("INTERVIEW_ASR_MODEL", "sense-asr-pro")
ASR_API_KEY = os.environ.get("INTERVIEW_ASR_API_KEY", os.environ.get("SENSEAUDIO_API_KEY", ""))
ASR_TIMEOUT = float(os.environ.get("INTERVIEW_ASR_TIMEOUT", "300"))
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
LLM_TIMEOUT = float(os.environ.get("INTERVIEW_LLM_TIMEOUT", "60"))
LLM_TEMPERATURE = float(os.environ.get("INTERVIEW_LLM_TEMPERATURE", "0.3"))
ASR_URL = os.environ.get("INTERVIEW_ASR_URL", "https://api.senseaudio.cn/v1/audio/transcriptions")
ASR_MODEL = os.environ.get("INTERVIEW_ASR_MODEL", "sense-asr-pro")
ASR_API_KEY = os.environ.get("INTERVIEW_ASR_API_KEY", os.environ.get("SENSEAUDIO_API_KEY", ""))
ASR_TIMEOUT = float(os.environ.get("INTERVIEW_ASR_TIMEOUT", "300"))
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
"voice_setting": {"voice_id": TTS_VOICE_ID},
"audio_setting": {"format": "mp3", "sample_rate": 32000},
}
response = requests.post(TTS_URL, headers=headers, json=payload, timeout=TTS_TIMEOUT)
response.raise_for_status()
result = response.json()
if result.get("base_resp", {}).get("status_code") != 0:
The script sends generated interview questions and the final summary text to an external TTS service without clearly informing the user. While less sensitive than raw audio in many cases, these prompts and summaries can still expose personal context, performance assessments, and job-target information to a third party.
When the user provides an audio file, the script uploads it to an external ASR service without an explicit consent or privacy notice at the decision point. Interview answers commonly contain personal information, employment history, and other sensitive content, so silent transmission to a third party creates a real privacy and compliance risk.
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
else:
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
report_path = OUTPUT_DIR / "final_report.json"
report_path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
print(f"完整结果已保存:{report_path}")
The manifest sets the skill's user-facing display name entirely in Chinese ("语音面试模拟器") with no indication that users can choose another language or locale. This can conflict with language/locale policy requirements when the skill is presented to a broader audience without explicit opt-in or justification.
The dependency specifier for openai is unpinned (>=1.30.0), which makes builds non-reproducible and allows future releases with breaking changes or newly introduced vulnerabilities to be installed automatically. This is a real supply-chain hygiene issue, though the file alone does not show active exploitation or a known vulnerable version.
openai>=1.30.0
requests>=2.31.0
python-dotenv>=1.0.0
requests>=2.31.0 is unpinned, so installations may resolve to different versions over time, including versions later found vulnerable or behaviorally incompatible. Because requests has a history of security advisories, leaving it unpinned increases uncertainty and supply-chain exposure.
openai>=1.30.0
requests>=2.31.0
python-dotenv>=1.0.0
requests has known advisories, and because the manifest does not pin a version, there is no way to verify from this file whether the installed version is affected or patched. In this skill context, the package is commonly used for network calls, so unresolved dependency versioning could matter if vulnerable code paths are present elsewhere in the project.
python-dotenv>=1.0.0 is also unpinned, which permits uncontrolled version drift and makes it impossible to guarantee which release is deployed. If the package later introduces or contains a vulnerable version in the allowed range, the environment could be exposed without any manifest change.
openai>=1.30.0
requests>=2.31.0
python-dotenv>=1.0.0
python-dotenv has known advisories, and without an exact version pin the project cannot demonstrate that it avoids affected releases. This is somewhat less dangerous in the current skill description because no direct .env file manipulation is shown here, but it still represents a real supply-chain verification gap.
No suspicious patterns detected.