Ssh Batch Manager

Security checks across malware telemetry and agentic risk

Overview

This is a real SSH key management skill, but it needs review because it can change access on many servers and installs a persistent Web UI with unsafe defaults.

Install only if you intentionally want this skill to administer SSH access across your servers. Before using it, review the server list and credential files, disable or harden the Web UI unless needed, bind it to 127.0.0.1, require explicit confirmation for both enable and disable operations, and avoid disabling SSH host key verification in production.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (51)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# Use printf which is safer than echo for arbitrary content
        cmd = f"printf '%s\\n' '{safe_pub_key}{safe_comment}' >> ~/.ssh/authorized_keys"
        
        subprocess.run(
            ['sshpass', '-e', 'ssh',
             '-o', 'StrictHostKeyChecking=no',
             '-o', 'UserKnownHostsFile=/dev/null',
Confidence
84% confidence
Finding
subprocess.run( ['sshpass', '-e', 'ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-o', f'Port={port}',

subprocess module call

Medium
Category
Dangerous Code Execution
Content
try:
        # 1. Create .ssh directory (using list arguments - safe)
        subprocess.run(
            ['sshpass', '-e', 'ssh',
             '-o', 'StrictHostKeyChecking=no',
             '-o', 'UserKnownHostsFile=/dev/null',
Confidence
98% confidence
Finding
subprocess.run( ['sshpass', '-e', 'ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-o', f'Port={port}',

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# Use printf which is safer than echo for arbitrary content
        cmd = f"printf '%s\\n' '{safe_pub_key}{safe_comment}' >> ~/.ssh/authorized_keys"
        
        subprocess.run(
            ['sshpass', '-e', 'ssh',
             '-o', 'StrictHostKeyChecking=no',
             '-o', 'UserKnownHostsFile=/dev/null',
Confidence
99% confidence
Finding
subprocess.run( ['sshpass', '-e', 'ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-o', f'Port={port}',

subprocess module call

Medium
Category
Dangerous Code Execution
Content
)
        
        # 3. Set permissions (using list arguments - safe)
        subprocess.run(
            ['sshpass', '-e', 'ssh',
             '-o', 'StrictHostKeyChecking=no',
             '-o', 'UserKnownHostsFile=/dev/null',
Confidence
98% confidence
Finding
subprocess.run( ['sshpass', '-e', 'ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-o', f'Port={port}',

subprocess module call

Medium
Category
Dangerous Code Execution
Content
timeout=30
        )
        
        subprocess.run(
            ['sshpass', '-e', 'ssh',
             '-o', 'StrictHostKeyChecking=no',
             '-o', 'UserKnownHostsFile=/dev/null',
Confidence
98% confidence
Finding
subprocess.run( ['sshpass', '-e', 'ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-o', f'Port={port}',

subprocess module call

Medium
Category
Dangerous Code Execution
Content
env['SSHPASS'] = password
    
    try:
        subprocess.run(
            ['sshpass', '-e', 'ssh',
             '-o', 'StrictHostKeyChecking=no',
             '-o', 'UserKnownHostsFile=/dev/null',
Confidence
98% confidence
Finding
subprocess.run( ['sshpass', '-e', 'ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-o', f'Port={port}',

subprocess module call

Medium
Category
Dangerous Code Execution
Content
timeout=30
        )
        
        subprocess.run(
            ['sshpass', '-e', 'ssh',
             '-o', 'StrictHostKeyChecking=no',
             '-o', 'UserKnownHostsFile=/dev/null',
Confidence
98% confidence
Finding
subprocess.run( ['sshpass', '-e', 'ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-o', f'Port={port}',

subprocess module call

Medium
Category
Dangerous Code Execution
Content
'-o', f'Port={port}',
                     user_host, 'test', '-f', '~/.ssh/authorized_keys']
        
        test_result = subprocess.run(check_cmd, env=env, capture_output=True, timeout=15)
        
        if test_result.returncode != 0:
            print(f"  {YELLOW}⚠️  authorized_keys not found, nothing to remove{NC}")
Confidence
97% confidence
Finding
test_result = subprocess.run(check_cmd, env=env, capture_output=True, timeout=15)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
'-o', f'Port={port}',
                    user_host, 'grep', '-F', key_data, '~/.ssh/authorized_keys']
        
        grep_result = subprocess.run(grep_cmd, env=env, capture_output=True, timeout=15)
        
        if grep_result.returncode != 0:
            print(f"  {YELLOW}⚠️  Key not found in authorized_keys, nothing to remove{NC}")
Confidence
97% confidence
Finding
grep_result = subprocess.run(grep_cmd, env=env, capture_output=True, timeout=15)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# When all lines are filtered, grep -Fv returns 1 and outputs nothing
        remove_cmd = f"KEY_DATA=$(echo '{key_b64}' | base64 -d); grep -Fv \"$KEY_DATA\" ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.tmp ; mv ~/.ssh/authorized_keys.tmp ~/.ssh/authorized_keys"
        
        subprocess.run(
            ['sshpass', '-e', 'ssh',
             '-o', 'StrictHostKeyChecking=no',
             '-o', 'UserKnownHostsFile=/dev/null',
Confidence
99% confidence
Finding
subprocess.run( ['sshpass', '-e', 'ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-o', f'Port={port}',

subprocess module call

Medium
Category
Dangerous Code Execution
Content
)
        
        # 4. Set permissions
        subprocess.run(
            ['sshpass', '-e', 'ssh',
             '-o', 'StrictHostKeyChecking=no',
             '-o', 'UserKnownHostsFile=/dev/null',
Confidence
98% confidence
Finding
subprocess.run( ['sshpass', '-e', 'ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-o', f'Port={port}',

subprocess module call

Medium
Category
Dangerous Code Execution
Content
)
        
        # 5. Verify key is removed
        verify_result = subprocess.run(grep_cmd, env=env, capture_output=True, timeout=15)
        
        if verify_result.returncode != 0:
            print(f"  {GREEN}✅ Key removed successfully{NC}")
Confidence
97% confidence
Finding
verify_result = subprocess.run(grep_cmd, env=env, capture_output=True, timeout=15)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
'-i', str(key_path),
                     user_host, 'test', '-f', '~/.ssh/authorized_keys']
        
        test_result = subprocess.run(check_cmd, capture_output=True, timeout=15)
        
        if test_result.returncode != 0:
            print(f"  {YELLOW}⚠️  authorized_keys not found, nothing to remove{NC}")
Confidence
96% confidence
Finding
test_result = subprocess.run(check_cmd, capture_output=True, timeout=15)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
'-i', str(key_path),
                    user_host, 'grep', '-F', key_data, '~/.ssh/authorized_keys']
        
        grep_result = subprocess.run(grep_cmd, capture_output=True, timeout=15)
        
        if grep_result.returncode != 0:
            print(f"  {YELLOW}⚠️  Key not found in authorized_keys, nothing to remove{NC}")
Confidence
96% confidence
Finding
grep_result = subprocess.run(grep_cmd, capture_output=True, timeout=15)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
key_b64 = base64.b64encode(key_data.encode()).decode()
        remove_cmd = f"KEY_DATA=$(echo '{key_b64}' | base64 -d); grep -Fv \"$KEY_DATA\" ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.tmp ; mv ~/.ssh/authorized_keys.tmp ~/.ssh/authorized_keys"
        
        subprocess.run(
            ['ssh',
             '-o', 'StrictHostKeyChecking=no',
             '-o', 'UserKnownHostsFile=/dev/null',
Confidence
99% confidence
Finding
subprocess.run( ['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-o', f'Port={port}', '-i', str(

subprocess module call

Medium
Category
Dangerous Code Execution
Content
)
        
        # 4. Set permissions
        subprocess.run(
            ['ssh',
             '-o', 'StrictHostKeyChecking=no',
             '-o', 'UserKnownHostsFile=/dev/null',
Confidence
98% confidence
Finding
subprocess.run( ['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-o', f'Port={port}', '-i', str(

subprocess module call

Medium
Category
Dangerous Code Execution
Content
)
        
        # 5. Verify key is removed
        verify_result = subprocess.run(grep_cmd, capture_output=True, timeout=15)
        
        if verify_result.returncode != 0:
            print(f"  {GREEN}✅ Key removed successfully{NC}")
Confidence
97% confidence
Finding
verify_result = subprocess.run(grep_cmd, capture_output=True, timeout=15)

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill advertises and documents use of shell execution, environment access, and local file read/write behavior, but no permissions are declared in the manifest. That prevents users or hosting platforms from making an informed trust decision and can allow unexpectedly broad local actions such as modifying SSH keys, credentials, and services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The stated purpose is batch SSH key management, but the documentation also describes installing a systemd service, running a local web server, managing local credential stores, and generating encryption and SSH keys. This scope expansion is security-relevant because users expecting a narrow admin utility may unknowingly install persistent services and broader local-management features.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The skill is presented as an SSH batch key-management tool, but the manifest also installs and auto-starts a local Web UI service via a post-install script. That expands the attack surface and persistence footprint beyond the declared purpose, which is risky because users may consent to SSH tooling without realizing they are also enabling a long-lived local service.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
Automatic systemd setup and Web UI startup are not necessary for the core SSH key distribution function described by the skill. Persisting a service at install time creates unnecessary system modification and can expose a management interface that handles sensitive SSH-related operations.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
Installing and auto-starting a local Web UI service via systemd materially changes the host and creates persistent local attack surface beyond simple SSH key distribution. Even if bound to localhost, a background service increases exposure to local abuse, browser-based interaction risks, and misconfiguration over time.

Description-Behavior Mismatch

Medium
Confidence
88% confidence
Finding
The documented encryption and file encrypt/decrypt utilities exceed the manifest's SSH batch-management purpose and introduce additional sensitive-data handling capability. Extra cryptographic and file-processing features enlarge the blast radius if the skill is misused or misunderstood, especially around credential and file secrecy.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
Auto-starting a Web UI is not obviously necessary for SSH batch key management and introduces persistence plus a new local control plane. Unnecessary always-on services increase the chance of accidental exposure, misuse by other local users/processes, and unnoticed long-term risk.

Intent-Code Divergence

Medium
Confidence
84% confidence
Finding
The documentation promises mandatory explicit confirmation before enable operations, but it also advertises a Web UI with quick enable actions without showing equivalent enforcement there. A mismatch between documented safety controls and UI behavior can lead to unauthorized or accidental SSH key deployment across multiple servers.

VirusTotal

66/66 vendors flagged this skill as clean.

View on VirusTotal