@neoline/hostbridge 1.4.3 → 1.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neoline/hostbridge",
3
- "version": "1.4.3",
3
+ "version": "1.4.4",
4
4
  "description": "HostBridge MCP server for persistent allowlisted SSH and shell sessions.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "hostbridge"
7
- version = "1.4.3"
7
+ version = "1.4.4"
8
8
  description = "HostBridge MCP server for persistent allowlisted SSH and shell sessions."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -28,6 +28,8 @@ MAX_SHELL_TRANSFER_BYTES = 100 * 1024 * 1024
28
28
  DEFAULT_MAX_TRANSFER_BYTES = MAX_SHELL_TRANSFER_BYTES
29
29
  UPLOAD_BASE64_CHUNK_CHARS = 256 * 1024
30
30
  DOWNLOAD_CHUNK_BYTES = 5 * 1024 * 1024
31
+ REMOTE_BASE64_DECODE_STDIN_CMD = "{ base64 --decode 2>/dev/null || base64 -d 2>/dev/null || base64 -D; }"
32
+ REMOTE_BASE64_ENCODE_CMD = "{ base64 --wrap=0 2>/dev/null || base64 | tr -d '\\n'; }"
31
33
 
32
34
  class PolicyDeniedError(RuntimeError):
33
35
  """Raised when a command is blocked by the configured policy."""
@@ -678,7 +680,7 @@ class SessionManager:
678
680
  finalize_script = (
679
681
  "set -e; "
680
682
  f"target={remote_q}; mode={mode_q}; tmp_b64={shlex.quote(tmp_b64)}; tmp_out={shlex.quote(tmp_out)}; "
681
- '{ base64 -d < "$tmp_b64" 2>/dev/null || base64 -D < "$tmp_b64"; } > "$tmp_out"; '
683
+ '{ base64 --decode < "$tmp_b64" 2>/dev/null || base64 -d < "$tmp_b64" 2>/dev/null || base64 -D < "$tmp_b64"; } > "$tmp_out"; '
682
684
  'chmod "$mode" "$tmp_out"; mv "$tmp_out" "$target"; rm -f "$tmp_b64"; '
683
685
  f"printf 'BYTES=%s\\nSHA256=%s\\n' {len(data)} {shlex.quote(sha256)}"
684
686
  )
@@ -787,7 +789,7 @@ class SessionManager:
787
789
  for index in range((byte_count + chunk_size - 1) // chunk_size):
788
790
  chunk_script = (
789
791
  "set -e; "
790
- f"dd if={remote_q} bs={chunk_size} skip={index} count=1 2>/dev/null | base64"
792
+ f"dd if={remote_q} bs={chunk_size} skip={index} count=1 2>/dev/null | {REMOTE_BASE64_ENCODE_CMD}"
791
793
  )
792
794
  output_limit = max(MAX_OUTPUT_CHARS, chunk_size * 2 + 4096)
793
795
  result = self.run_command(
@@ -899,7 +901,8 @@ class SessionManager:
899
901
  def _build_remote_line(self, command: str, token: str, start_marker: str) -> str:
900
902
  encoded_command = base64.b64encode(command.encode("utf-8")).decode("ascii")
901
903
  return (
902
- f"__scm_cmd=$(printf %s {shlex.quote(encoded_command)} | {{ base64 --decode 2>/dev/null || base64 -D; }}); "
904
+ f"__scm_cmd=$(printf %s {shlex.quote(encoded_command)} | "
905
+ f"{REMOTE_BASE64_DECODE_STDIN_CMD}); "
903
906
  f"printf '\\n{start_marker}\\n'; "
904
907
  f"{self.remote_shell} -lc \"$__scm_cmd\"; "
905
908
  "__scm_status=$?; "