fix(security): reduce unnecessary shell=True in subprocess calls

- memory_setup.py: use shlex.split() for plugin dep checks instead of shell=True
- transcription_tools.py: avoid shell=True for auto-detected whisper commands
  (user-provided templates via env var still use shell=True for compatibility)
- cli.py: add comment clarifying intentional shell=True for user quick_commands
- Add test verifying auto-detected template is shlex-safe

Addresses CONTRIBUTING.md Priority #3 (Security hardening — shell injection).
This commit is contained in:
iuyup 2026-04-08 20:44:34 +08:00 committed by Teknium
parent a9b8254e5f
commit d6c9711ba8
4 changed files with 53 additions and 2 deletions

View file

@ -1363,3 +1363,45 @@ class TestTranscribeAudioXAIDispatch:
transcribe_audio(sample_ogg, model="custom-stt")
assert mock_xai.call_args[0][1] == "custom-stt"
# ============================================================================
# Shell safety — shlex.split on auto-detected templates
# ============================================================================
class TestShellSafety:
def test_auto_detected_template_is_shlex_safe(self, monkeypatch):
"""Auto-detected whisper command should be safely splittable."""
import shlex
monkeypatch.delenv("HERMES_LOCAL_STT_COMMAND", raising=False)
monkeypatch.setattr(
"tools.transcription_tools._find_whisper_binary",
lambda: "/usr/bin/whisper",
)
from tools.transcription_tools import _get_local_command_template
template = _get_local_command_template()
assert template is not None
cmd = template.format(
input_path=shlex.quote("/tmp/test.wav"),
output_dir=shlex.quote("/tmp/out"),
language=shlex.quote("en"),
model=shlex.quote("base"),
)
parts = shlex.split(cmd)
assert parts[0] == "/usr/bin/whisper"
assert "/tmp/test.wav" in parts
def test_env_var_template_uses_shell_path(self, monkeypatch):
"""When HERMES_LOCAL_STT_COMMAND is set, use_shell should be True."""
import os
from tools.transcription_tools import LOCAL_STT_COMMAND_ENV
monkeypatch.setenv(LOCAL_STT_COMMAND_ENV, "whisper {input_path} | tee log.txt")
use_shell = bool(os.getenv(LOCAL_STT_COMMAND_ENV, "").strip())
assert use_shell is True
def test_no_env_var_uses_list_mode(self, monkeypatch):
"""When no env var is set, use_shell should be False."""
import os
from tools.transcription_tools import LOCAL_STT_COMMAND_ENV
monkeypatch.delenv(LOCAL_STT_COMMAND_ENV, raising=False)
use_shell = bool(os.getenv(LOCAL_STT_COMMAND_ENV, "").strip())
assert use_shell is False