T09 · Insecure Skill Coding Practices
- Location
scripts/voice_pipeline.py:348- Finding
Multiple live-looking API credentials are hardcoded in source code and documentation
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This appears to be a real voice-assistant skill, but it needs review because it runs an always-listening microphone, sends voice data to cloud services, controls Home Assistant devices, and contains serious credential and authentication weaknesses.
Install only after reviewing the cloud data flows and device-control permissions. Rotate any embedded credentials, require explicit user-provided secrets, use HTTPS or localhost-only Home Assistant endpoints with least-privilege tokens, make speaker verification fail closed, avoid joblib/pickle loading from untrusted writable paths, and do not run it as an always-on service unless the microphone and cloud-processing behavior are acceptable.
scripts/voice_pipeline.py:348Multiple live-looking API credentials are hardcoded in source code and documentation
scripts/voice_pipeline.py:343Microphone audio, transcripts, conversation history, and response text are sent to cloud services despite offline positioning
scripts/voice_pipeline_v2.py:313Sensitive voice recordings and biometric enrollment samples are retained under predictable temporary paths
scripts/speaker_verification.py:76Speaker verification fails open and permits commands after verification errors
scripts/speaker_verification.py:80Untrusted joblib model deserialization can execute arbitrary code as the service user
scripts/voice_pipeline_v2.py:717Home Assistant bearer credentials and control commands are transmitted over plaintext HTTP by default
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
_chat_history = _chat_history[-10:]
try:
resp = requests.post(
_OPENROUTER_URL,
headers={"Authorization": f"Bearer {_OPENROUTER_KEY}",
"Content-Type": "application/json"},
This code transmits captured voice audio to Groq's external STT service, contradicting the skill's 'offline' description and exposing sensitive spoken content to a third party. In a voice-assistant context, commands may contain private household information, credentials, or behavioral data, making this materially risky even if the API key flow itself is normal.
log.warning(f"Could not save last command WAV: {e}")
# Call Groq API
resp = requests.post(
"https://api.groq.com/openai/v1/audio/transcriptions",
headers={"Authorization": f"Bearer {GROQ_API_KEY}"},
files={"file": ("audio.wav", wav_io, "audio/wav")},
The code sends user voice-derived prompts to an HTTP-configurable gateway URL, which may forward them to another agent with tool access. Because the endpoint is environment-controlled and defaults to localhost but can be redirected, sensitive commands can be exfiltrated or routed to an untrusted service without clear safeguards.
)
try:
resp = requests.post(
f"{gateway_url}/tools/invoke",
headers={
"Authorization": f"Bearer {gateway_token}",
This sends device-control requests plus a bearer token to a configurable Home Assistant URL, so if HA_URL is changed to an attacker-controlled host the token and command data could be exposed. In this skill, that could enable unauthorized smart-home control or token theft affecting the broader home-automation environment.
# Call HA API
url = f"{HA_URL}/api/services/{service}"
resp = requests.post(
url,
headers={"Authorization": f"Bearer {HA_TOKEN}",
"Content-Type": "application/json"},
The combination of 'offline voice pipeline' marketing with described external LLM/gateway usage and an always-listening microphone materially understates the privacy and capability surface. In this context, omitted disclosure around network APIs, device control, and sensitive voice-related processing makes the skill more dangerous because users are likely to deploy it on personal, always-on hardware inside homes.
The combination of 'offline voice pipeline' marketing with described external LLM/gateway usage and an always-listening microphone materially understates the privacy and capability surface. In this context, omitted disclosure around network APIs, device control, and sensitive voice-related processing makes the skill more dangerous because users are likely to deploy it on personal, always-on hardware inside homes.
The combination of 'offline voice pipeline' marketing with described external LLM/gateway usage and an always-listening microphone materially understates the privacy and capability surface. In this context, omitted disclosure around network APIs, device control, and sensitive voice-related processing makes the skill more dangerous because users are likely to deploy it on personal, always-on hardware inside homes.
The combination of 'offline voice pipeline' marketing with described external LLM/gateway usage and an always-listening microphone materially understates the privacy and capability surface. In this context, omitted disclosure around network APIs, device control, and sensitive voice-related processing makes the skill more dangerous because users are likely to deploy it on personal, always-on hardware inside homes.
The combination of 'offline voice pipeline' marketing with described external LLM/gateway usage and an always-listening microphone materially understates the privacy and capability surface. In this context, omitted disclosure around network APIs, device control, and sensitive voice-related processing makes the skill more dangerous because users are likely to deploy it on personal, always-on hardware inside homes.
The combination of 'offline voice pipeline' marketing with described external LLM/gateway usage and an always-listening microphone materially understates the privacy and capability surface. In this context, omitted disclosure around network APIs, device control, and sensitive voice-related processing makes the skill more dangerous because users are likely to deploy it on personal, always-on hardware inside homes.
The notes document a voice pipeline that sends audio to external cloud providers and couples the assistant to remote Home Assistant control, which materially exceeds the stated 'offline Jetson' scope. That mismatch can mislead reviewers and users about data flows and trust boundaries, increasing the risk of unauthorized disclosure of voice data and unintended device control.
Reading Home Assistant tokens from local config and using them to issue REST control commands grants the pipeline access to sensitive credentials and direct control over connected devices. In a voice assistant context, this is particularly dangerous because misrecognition, prompt manipulation, or abuse of the LLM-to-command path can trigger unauthorized actions in the physical environment.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
edge-tts --voice en-US-AndrewNeural --text "Alfred voice pipeline test successful." \
--write-media /tmp/alfred-test.mp3 --write-subtitles /dev/null
mpg123 -q -a hw:C2c,0 /tmp/alfred-test.mp3
rm -f /tmp/alfred-test.mp3
;;
test-mic)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
"
echo "▶ Playing back recording..."
aplay -q -D plughw:C2c,0 /tmp/alfred-mic-test.wav
rm -f /tmp/alfred-mic-test.raw /tmp/alfred-mic-test.wav
;;
test-stt)
When no model file exists, verify_speaker() returns (True, 0.0, 0.0), granting verification success instead of denying access or signaling an unenrolled state. In a voice-gated system, this creates a trivial authentication bypass: deleting, renaming, or preventing creation of the model file disables the protection entirely.
The exception handler returns successful verification on any system error, including corrupted model files, deserialization problems, malformed audio handling, or runtime faults. An attacker who can trigger such errors can bypass speaker verification without matching the enrolled voice, undermining the entire security control.
The script labeled as part of an 'offline' voice pipeline performs live network checks against Groq, Anthropic, and Home Assistant, which expands the trust boundary and can transmit credentials or data off-device. This is not just a documentation mismatch: users may run it expecting offline-only behavior, but it validates and exercises external integrations with real tokens.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
SIZE=$(stat -f%z /tmp/alfred-test.raw 2>/dev/null || stat -c%s /tmp/alfred-test.raw 2>/dev/null || echo 0)
if [ "$SIZE" -gt 1000 ]; then
echo "✅ Mic recording successful ($SIZE bytes)"
rm /tmp/alfred-test.raw
else
echo "❌ Mic recording too small"
fi
A hardcoded fallback Anthropic API key is a real secret-handling vulnerability. Embedding a usable credential in source code enables unauthorized use, accidental redistribution, billing abuse, and makes operators unknowingly send requests under someone else's account.
The file advertises a 'fully offline' voice pipeline, but the implementation sends captured microphone audio to Groq and sends conversation text to OpenRouter. This is dangerous because users and operators may make trust and privacy decisions based on false offline claims, causing sensitive voice data to be exfiltrated unexpectedly.
The comments state that only the Claude API requires internet, but the code also uploads audio to Groq Whisper for transcription. Hidden additional network paths increase privacy and compliance risk because operators cannot accurately assess what data leaves the device.
The STT section is described as offline/local, yet the actual transcription code posts audio to a remote Groq endpoint. This mismatch is especially dangerous in a voice skill because raw microphone captures can contain highly sensitive personal or environmental information.
The code transmits recorded microphone audio to an external transcription API without clear just-in-time disclosure to the user. In a voice-assistant context this is particularly sensitive because users may reasonably expect local processing based on the skill description, while private speech is actually being uploaded off-device.
A hardcoded bearer token for a third-party transcription service is embedded directly in source code. This is dangerous because anyone with source or log access can reuse the credential, incur charges, impersonate the service identity, or access associated account resources.
The header markets the pipeline as 'offline', yet the implementation sends audio, prompts, and search queries to multiple external services. This mismatch is dangerous because users and operators may make trust and privacy decisions based on the false assumption that voice data never leaves the device.
Detected: suspicious.exposed_secret_literal