
Research
/Security News
Critical Vulnerability in NestJS Devtools: Localhost RCE via Sandbox Escape
A flawed sandbox in @nestjs/devtools-integration lets attackers run code on your machine via CSRF, leading to full Remote Code Execution (RCE).
High-performance SSH library with unified API for direct and jump host connections
A high-performance SSH library with unified API for direct and jump host connections.
SSHClient
class for both direct and jump host connectionspip install ssh-anywhere
git clone https://github.com/wbx13/ssh.git
cd ssh
pip install -e .
git clone https://github.com/wbx13/ssh.git
cd ssh
poetry install
from ssh import SSHClient
# Create client for direct connection
client = SSHClient(
hostname="example.com",
username="user",
private_key_path="~/.ssh/id_rsa"
)
# Execute command
result = client.exec_cmd("hostname")
print(result.stdout)
# Start interactive session
client.interact()
from ssh import SSHClient
# Create jump host client
jump_host = SSHClient(
hostname="jump.example.com",
username="jump_user",
private_key_path="~/.ssh/id_rsa"
)
# Create target client through jump host
target = SSHClient(
hostname="10.0.0.100",
username="target_user",
password="password",
jump_host=jump_host # Pass the jump host client
)
# Execute command on target through jump host
result = target.exec_cmd("get system status")
print(result.stdout)
# Chain multiple jump hosts
jump1 = SSHClient(hostname="jump1.example.com", username="user")
jump2 = SSHClient(hostname="jump2.example.com", username="user", jump_host=jump1)
target = SSHClient(hostname="target.example.com", username="user", jump_host=jump2)
# Execute commands through the chain
result = target.exec_cmd("hostname")
For configuration workflows that require maintaining session state:
from ssh import SSHClient
client = SSHClient(
hostname="firewall.example.com",
username="admin",
password="password"
)
# Execute multiple commands while preserving state
commands = [
'config system interface',
'show',
'edit port1',
'set description "Updated via SSH"',
'show',
'end'
]
results = client.exec_sequential_commands(commands, timeout=60)
# Each command gets its own CommandResult
for i, (cmd, result) in enumerate(zip(commands, results)):
print(f"Command {i+1}: {cmd}")
print(f"Success: {result.success}")
print(f"Output: {result.stdout[:100]}...") # First 100 chars
The main class for SSH connections.
Parameter | Type | Default | Description |
---|---|---|---|
hostname | str | Required | Target hostname or IP address |
username | str | Current user | SSH username |
port | int | 22 | SSH port |
password | str | None | Password for authentication |
private_key_path | str | None | Path to private key file |
jump_host | SSHClient | None | Another SSHClient instance to use as jump host |
ssh_options | dict | None | Additional SSH options |
establish_master | bool | True | Whether to establish control master on init |
Method | Description |
---|---|
exec_cmd(command, timeout=30) | Execute a command and return CommandResult |
exec_sequential_commands(commands, timeout=60, command_delay=0.5) | Execute multiple commands sequentially while maintaining session state |
interact(escape_char='~') | Start an interactive SSH session |
Result object returned by exec_cmd()
.
Property | Type | Description |
---|---|---|
returncode | int | Exit code of the command |
stdout | str | Standard output as string |
stderr | str | Standard error as string |
success | bool | Boolean indicating if command succeeded (returncode == 0) |
Function | Description |
---|---|
cleanup_ssh_sockets() | Clean up all SSH control sockets |
# If installed as package
ssh-demo
# Or run directly
python examples/unified_demo.py
Create a .env
file for the demo:
JUMP_HOST=jump.example.com
JUMP_USERNAME=jump_user
JUMP_KEY_PATH=~/.ssh/jump_key
TARGET_HOST=target.example.com
TARGET_USERNAME=target_user
TARGET_PASSWORD=target_password
# Clone the repository
git clone https://github.com/wbx13/ssh.git
cd ssh
# Install with Poetry
poetry install
# Install pre-commit hooks
poetry run pre-commit install
# Run tests
poetry run pytest
# Run linting
poetry run black src/ tests/ examples/
poetry run isort src/ tests/ examples/
poetry run flake8 src/ tests/ examples/
# All tests
poetry run pytest
# With coverage
poetry run pytest --cov=src --cov-report=html
# Specific test file
poetry run pytest tests/test_client.py -v
ssh
command) - Usually pre-installed on Unix systemssudo apt install expect
brew install expect
(or use built-in version)sudo yum install expect
All Python dependencies are managed through Poetry and specified in pyproject.toml
.
We welcome contributions! Please see our Contributing Guide for details.
Please see our Security Policy for information on reporting security vulnerabilities.
This project is licensed under the MIT License - see the LICENSE file for details.
See CHANGELOG.md for a detailed list of changes and version history.
Documentation • Issues • Discussions
Made with ❤️ for the Python community
FAQs
High-performance SSH library with unified API for direct and jump host connections
We found that ssh-anywhere demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
A flawed sandbox in @nestjs/devtools-integration lets attackers run code on your machine via CSRF, leading to full Remote Code Execution (RCE).
Product
Customize license detection with Socket’s new license overlays: gain control, reduce noise, and handle edge cases with precision.
Product
Socket now supports Rust and Cargo, offering package search for all users and experimental SBOM generation for enterprise projects.