github Python re-analysis due

zb-ss/servonaut

github

Manage AWS, Hetzner, OVH, and custom servers from one TUI — with a built-in AI assistant and MCP server

maintainer
zb-ss
licence
MIT
first seen
2026-06-04
last seen
2026-09-17
releases · 30d
8
short id

Drift inferred · capture-to-capture

No drift recorded — single capability capture; advisories appear once its surface changes.

capabilities 0 tools
transport stdio · http counts 0 tools · 0 res · 0 prompts permission surface via code analysis

No tools enumerated yet for this server.

skills & danger signals github-tarball
prompt-surface shipped agent-instruction files + hidden-content / dangerous-code findings — quoted from the analyzed source

analyzed commit 9aae544 · analyzer v33 · 3d ago

danger signals4

code evidence vv2.26.2 · github-tarball
evidence-backed findings quoted directly from the published source artifact — not inferred

code files: 601

filesystem 161

  • fs (weak) zb-ss-servonaut-9aae544/.github/scripts/release-policy.py :9 from pathlib import Path
  • fs (weak) zb-ss-servonaut-9aae544/scripts/desktop_probe/check.py :14 from pathlib import Path
  • fs (weak) zb-ss-servonaut-9aae544/scripts/desktop_probe/child.py :11 from pathlib import Path
  • fs (weak) zb-ss-servonaut-9aae544/scripts/desktop_probe/config.py :5 from pathlib import Path
  • fs (weak) zb-ss-servonaut-9aae544/scripts/desktop_probe/diagnostics.py :9 from pathlib import Path
  • fs (weak) zb-ss-servonaut-9aae544/scripts/desktop_probe/host.py :14 from pathlib import Path
  • fs (weak) zb-ss-servonaut-9aae544/scripts/desktop_probe/renderer.py :3 # Upstream registers WebGL and then replaces it with Canvas during open().
  • fs zb-ss-servonaut-9aae544/src/servonaut/cli/ai.py :51 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/cli/hetzner.py :43 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/cli/login.py :151 if webbrowser.open(open_target):
  • fs zb-ss-servonaut-9aae544/src/servonaut/cli/memory.py :12 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/cli/secrets.py :46 import shutil
show 28 more
  • fs zb-ss-servonaut-9aae544/src/servonaut/config/manager.py :7 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/config/migration.py :7 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/config/paths.py :26 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/config/secrets.py :7 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/main.py :11 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/mcp/audit.py :20 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/mcp/installer.py :8 import shutil
  • fs zb-ss-servonaut-9aae544/src/servonaut/mcp/tools.py :3912 from pathlib import Path as _Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/ai_conversations_screen.py :22 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/backup_restore.py :7 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/bug_report.py :394 webbrowser.open(receipt.url)
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/bw_dir_picker.py :19 Dismisses the chosen :class:`~pathlib.Path`, or ``None`` on cancel.
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/bw_item_picker.py :293 webbrowser.open(_PRICING_URL)
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/bw_key_import.py :21 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/bw_vault_manager.py :369 webbrowser.open(url)
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/findings.py :767 webbrowser.open(url)
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/fleet_memory.py :21 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/hetzner_setup.py :381 import shutil
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/ip_ban.py :132 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/key_management.py :219 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/memory.py :16 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/memory_sync_setup.py :523 webbrowser.open(url)
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/ovh_setup.py :392 import shutil
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/scp_transfer.py :105 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/secrets.py :600 webbrowser.open(url)
  • fs zb-ss-servonaut-9aae544/src/servonaut/screens/server_actions.py :1341 os.unlink(tmp_key_path)
  • fs zb-ss-servonaut-9aae544/src/servonaut/services/ai_conversations.py :20 from pathlib import Path
  • fs zb-ss-servonaut-9aae544/src/servonaut/services/ai_providers/demo_replay.py :39 from pathlib import Path

121 more not shown — this panel samples each group; the count above is the real total.

shell / exec 40

  • shell (weak) zb-ss-servonaut-9aae544/.github/scripts/release-policy.py :6 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/cli/memory.py :10 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/cli/secrets.py :47 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/cli/servers.py :21 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/cli/ssh.py :22 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/main.py :412 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/mcp/installer.py :9 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/screens/command_overlay.py :5 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/screens/hetzner_setup.py :382 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/screens/key_management.py :4 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/screens/log_viewer.py :8 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/screens/memory.py :14 import subprocess
show 28 more
  • shell zb-ss-servonaut-9aae544/src/servonaut/screens/ovh_setup.py :393 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/screens/server_actions.py :6 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/services/bw_resolver.py :22 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/services/bw_session_service.py :32 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/services/memory/service.py :1306 from subprocess import CalledProcessError
  • shell zb-ss-servonaut-9aae544/src/servonaut/services/scan_service.py :7 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/services/scp_service.py :7 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/services/ssh_service.py :6 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/services/terminal_service.py :6 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/services/update_service.py :8 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/utils/platform_utils.py :6 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/utils/ssh_utils.py :7 import subprocess
  • shell zb-ss-servonaut-9aae544/src/servonaut/widgets/remote_tree.py :5 import subprocess
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_bw_key_import.py :14 import subprocess
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_bw_resolver.py :6 from subprocess import CompletedProcess
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_bw_session_service.py :13 from subprocess import CompletedProcess, TimeoutExpired
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_cli_servers.py :15 import subprocess
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_css_paths.py :17 import subprocess
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_demo_mode_coverage.py :958 import subprocess
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_desktop_probe_native.py :7 import subprocess
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_docs_cli_commands.py :14 import subprocess
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_mcp_headless_imports.py :11 import subprocess
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_memory_cli.py :318 import subprocess as _subprocess
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_relay_lock.py :72 import subprocess
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_release_policy.py :6 import subprocess
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_remediation_executor.py :345 import subprocess
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_remote_tree_sudo_fallback.py :106 import subprocess as _sp
  • shell (weak) zb-ss-servonaut-9aae544/tests/test_ssh_utils.py :5 import subprocess

network 40

  • net (weak) zb-ss-servonaut-9aae544/scripts/desktop_probe/__main__.py :14 import socket
  • net (weak) zb-ss-servonaut-9aae544/scripts/desktop_probe/host.py :10 import socket
  • net zb-ss-servonaut-9aae544/src/servonaut/app.py :2285 "Bug reporting requires httpx. Install with: pip install 'servonaut[pro]'",
  • net zb-ss-servonaut-9aae544/src/servonaut/main.py :548 if we simply don't have credentials or httpx.
  • net zb-ss-servonaut-9aae544/src/servonaut/mcp/remote_client.py :16 import httpx
  • net zb-ss-servonaut-9aae544/src/servonaut/mcp/tools.py :1077 import httpx
  • net zb-ss-servonaut-9aae544/src/servonaut/screens/cloudwatch_browser.py :652 import httpx
  • net zb-ss-servonaut-9aae544/src/servonaut/screens/snapshot_manager.py :388 import socket
  • net zb-ss-servonaut-9aae544/src/servonaut/services/ai_analysis_service.py :21 import httpx
  • net zb-ss-servonaut-9aae544/src/servonaut/services/ai_providers/demo_replay.py :42 import httpx
  • net zb-ss-servonaut-9aae544/src/servonaut/services/ai_sse.py :5 underlying :class:`httpx.AsyncClient` lifetime via ``async with`` so a
  • net zb-ss-servonaut-9aae544/src/servonaut/services/api_client.py :18 import httpx
show 28 more
  • net zb-ss-servonaut-9aae544/src/servonaut/services/auth_service.py :18 import httpx
  • net zb-ss-servonaut-9aae544/src/servonaut/services/bug_report_service.py :14 import urllib.parse
  • net zb-ss-servonaut-9aae544/src/servonaut/services/config_sync_service.py :9 import socket
  • net zb-ss-servonaut-9aae544/src/servonaut/services/db_credential_scanner.py :25 from urllib.parse import urlparse, unquote
  • net zb-ss-servonaut-9aae544/src/servonaut/services/ip_enrichment_service.py :27 import urllib.request
  • net zb-ss-servonaut-9aae544/src/servonaut/services/object_storage_service.py :8 import socket
  • net zb-ss-servonaut-9aae544/src/servonaut/services/ovh_ip_service.py :9 from urllib.parse import quote
  • net zb-ss-servonaut-9aae544/src/servonaut/services/relay_listener.py :10 import socket
  • net zb-ss-servonaut-9aae544/src/servonaut/services/relay_manager.py :22 from urllib.parse import urlsplit, urlunsplit
  • net zb-ss-servonaut-9aae544/src/servonaut/services/update_service.py :10 import urllib.request
  • net zb-ss-servonaut-9aae544/src/servonaut/services/voice_setup_service.py :973 import httpx
  • net (weak) zb-ss-servonaut-9aae544/tests/sse_replay.py :3 Turns a ``.sse`` byte fixture into an :class:`httpx.MockTransport` that
  • net (weak) zb-ss-servonaut-9aae544/tests/test_api_client_errors.py :39 """Build a minimal mock that looks like an httpx.Response."""
  • net (weak) zb-ss-servonaut-9aae544/tests/test_auth_service.py :586 """Bare-minimum httpx.Response stand-in for refresh_token unit tests."""
  • net (weak) zb-ss-servonaut-9aae544/tests/test_demo_chat_replay.py :8 import httpx
  • net (weak) zb-ss-servonaut-9aae544/tests/test_desktop_probe.py :46 async with aiohttp.ClientSession() as client:
  • net (weak) zb-ss-servonaut-9aae544/tests/test_desktop_probe_browser.py :10 from urllib.parse import parse_qs, urlsplit
  • net (weak) zb-ss-servonaut-9aae544/tests/test_findings_service.py :22 import httpx
  • net (weak) zb-ss-servonaut-9aae544/tests/test_mcp_api_request.py :73 """Collects the last httpx.Request observed by the mock transport."""
  • net (weak) zb-ss-servonaut-9aae544/tests/test_mcp_relay_reconnect.py :66 real = httpx.AsyncClient
  • net (weak) zb-ss-servonaut-9aae544/tests/test_mcp_relay_status_and_tool_call.py :61 real = httpx.AsyncClient
  • net (weak) zb-ss-servonaut-9aae544/tests/test_relay_handshake.py :245 import httpx
  • net (weak) zb-ss-servonaut-9aae544/tests/test_secret_provider_resolver.py :307 # E.g. httpx.ConnectError / generic OSError — should not log
  • net (weak) zb-ss-servonaut-9aae544/tests/test_secrets_audit_fixes.py :108 "servonaut.services.api_client.httpx.AsyncClient",
  • net (weak) zb-ss-servonaut-9aae544/tests/test_secrets_config_api_client.py :6 against the live endpoint. Mocks at the httpx.AsyncClient layer
  • net (weak) zb-ss-servonaut-9aae544/tests/test_secrets_followups.py :175 "servonaut.services.auth_service.httpx.AsyncClient",
  • net (weak) zb-ss-servonaut-9aae544/tests/test_sse_stream.py :279 ``async with httpx.AsyncClient`` in :func:`stream_sse` unwound.
  • net (weak) zb-ss-servonaut-9aae544/tests/test_user_secrets_config.py :95 "servonaut.services.api_client.httpx.AsyncClient",

secrets 7

  • secrets zb-ss-servonaut-9aae544/src/servonaut/cli/memory.py :6 import getpass
  • secrets zb-ss-servonaut-9aae544/src/servonaut/main.py :221 auth_token = os.environ.get('SERVONAUT_RELAY_TOKEN', '')
  • secrets zb-ss-servonaut-9aae544/src/servonaut/screens/memory.py :9 import getpass
  • secrets zb-ss-servonaut-9aae544/src/servonaut/services/hetzner_service.py :164 from_env = os.environ.get('HCLOUD_TOKEN', '')
  • secrets zb-ss-servonaut-9aae544/src/servonaut/services/memory/passphrase_store.py :31 import keyring as _keyring # type: ignore[import-untyped]
  • secrets (weak) zb-ss-servonaut-9aae544/tests/test_e2e_secrets_staging.py :119 oauth = os.environ.get("SERVONAUT_E2E_OAUTH_TOKEN", "")
  • secrets (weak) zb-ss-servonaut-9aae544/tests/test_secrets.py :134 assert os.environ["GOOD_KEY"] == "good_val"

declared dependencies 20

  • mcp@>=1.0.0,<2
  • boto3@*
  • tabulate@*
  • textual@>=8.0.0
  • cryptography@>=42.0
  • bcrypt@>=3.2
  • pynacl@>=1.5
  • httpx@>=0.25.0
  • httpx-sse@>=0.4
  • keyring@>=24
  • pytest@>=7.0
  • pytest-cov@>=4.0
show 8 more
  • pytest-asyncio@>=0.21
  • pytest-timeout@>=2.3
  • ovh@*
  • hcloud@>=2.0
  • faster-whisper@>=1.0
  • sounddevice@>=0.4
  • numpy@>=1.24
  • sherpa-onnx@>=1.13.3

clipboard 1

  • clipboard shell call zb-ss-servonaut-9aae544/src/servonaut/utils/platform_utils.py :94 subprocess.run(['pbcopy'], input=text.encode(), check=True)