fix(security): scrub credentials from voice playback subprocesses
## Summary - Spawn system audio players (`ffplay` / `afplay` / `aplay`) with `hermes_subprocess_env(inherit_credentials=False)`. - Prevent gateway tokens and provider API keys from leaking into OS media helpers. - Add a regression test asserting scrubbed env on `Popen`. ## Salvage / credit Sibling of #70342 / incomplete #56332 (TTS/STT command scrub) on the voice-mode playback path.
This commit is contained in:
parent
24a6fb6448
commit
3ae25e0fbd
|
|
@ -0,0 +1,32 @@
|
|||
"""Voice-mode system playback must scrub credential env (sibling of #70342)."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
|
||||
def test_play_audio_file_scrubbed_env(tmp_path, monkeypatch):
|
||||
audio = tmp_path / "t.mp3"
|
||||
audio.write_bytes(b"ID3fake")
|
||||
|
||||
monkeypatch.setenv("TELEGRAM_BOT_TOKEN", "secret-token")
|
||||
monkeypatch.setenv("OPENAI_API_KEY", "sk-test")
|
||||
|
||||
captured = {}
|
||||
|
||||
def fake_popen(cmd, **kwargs):
|
||||
captured["env"] = kwargs.get("env")
|
||||
proc = MagicMock()
|
||||
proc.wait.return_value = 0
|
||||
return proc
|
||||
|
||||
import tools.voice_mode as vm
|
||||
|
||||
with patch.object(vm, "platform") as plat, patch.object(
|
||||
vm.shutil, "which", return_value="/usr/bin/ffplay"
|
||||
), patch.object(vm.subprocess, "Popen", side_effect=fake_popen):
|
||||
plat.system.return_value = "Linux"
|
||||
ok = vm.play_audio_file(str(audio))
|
||||
|
||||
assert ok is True
|
||||
assert captured.get("env") is not None
|
||||
assert "TELEGRAM_BOT_TOKEN" not in captured["env"]
|
||||
assert "OPENAI_API_KEY" not in captured["env"]
|
||||
|
|
@ -1510,7 +1510,17 @@ def play_audio_file(file_path: str) -> bool:
|
|||
exe = shutil.which(cmd[0])
|
||||
if exe:
|
||||
try:
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdin=subprocess.DEVNULL)
|
||||
# Sibling of TTS/STT credential scrub (#70342 / #56332): system
|
||||
# audio players must not inherit gateway tokens / API keys.
|
||||
from tools.environments.local import hermes_subprocess_env
|
||||
|
||||
proc = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
stdin=subprocess.DEVNULL,
|
||||
env=hermes_subprocess_env(inherit_credentials=False),
|
||||
)
|
||||
with _playback_lock:
|
||||
_active_playback = proc
|
||||
proc.wait(timeout=300)
|
||||
|
|
|
|||
Loading…
Reference in New Issue