Back to skill

Security audit

Mikrotik

Security checks for vulnerabilities and agentic risk

Overview

This skill is for router administration, but it handles powerful network access and router credentials in ways users should review carefully before installing.

Install only in a network you administer and preferably in a lab or isolated management environment. Do not put real router administrator passwords in TOOLS.md or command-line arguments, avoid blank/default admin credentials, prefer a least-privileged RouterOS account, and treat scanning plus custom commands as potentially disruptive operations that need explicit approval.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (5)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
mikrotik-api/scanner.py:120
Finding
Automatic Local-Network Reconnaissance and Default-Credential Authentication Attempts<![CDATA[ ## Vulnerability Details **File Location**: `mikrotik-api/scanner.py:120-199`, with subnet enumeration and concurrent scanning at `mikrotik-api/scanner.py:208-303` **Vulnerability Type**: Automatic network discovery, port scanning, and default-credential authentication **Risk Level**: High ### Vulnerable Code ```python def scan_ip(self, ip: str, arp_macs: Dict[str, str]) -> Optional[Dict]: try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(self.timeout) result = sock.connect_ex((ip, self.API_PORT)) if result == 0: mac = arp_macs.get(ip, 'Unknown') is_mikrotik = mac != 'Unknown' and any( mac.startswith(oui) for oui in self.MIKROTIK_OUIS ) device = { 'ip': ip, 'mac': mac, 'port': self.API_PORT, 'identity': 'Unknown', 'model': 'Unknown', 'version': '', 'source': 'api_port', 'is_mikrotik': is_mikrotik } if is_mikrotik: try: from client import MikroTikAPI api = MikroTikAPI(ip, 'admin', '', timeout=2) if api.connect(): if api.login(): result = api.run_command('/system/identity/print') if result: device['identity'] = result[0].get('name', 'Unknown') result = api.run_command('/system/resource/print') if result: device['version'] = result[0].get('version', '') api.disconnect() except: pass ``` The scan is applied to every usable address in locally discovered subnets: ```python for ip_int in range(network_masked + 1, broadcast): ip = socket. ...[truncated 2286 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove all authentication attempts from device discovery. Discovery should only report explicitly requested open ports. 2. Require the user to provide an authorized target CIDR instead of automatically scanning every local subnet. 3. Display the target range and require explicit confirmation before transmitting probe traffic. 4. Enforce a maximum address count, subnet-size limit, concurrency limit, and total scan timeout. 5. Maintain an allowlist of approved networks and reject multicast, public, cloud metadata, and other sensitive ranges. 6. Never try default or empty credentials automatically. Require credentials to be supplied for one explicitly selected device after discovery. 7. Log the authorization decision, requested range, start time, and scan volume. 8. Clearly separate passive inventory, active port scanning, and authenticated inspection into distinct operations. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
handler.py:28
Finding
Plaintext Router Administrator Credentials in a Shared Workspace File<![CDATA[ ## Vulnerability Details **File Location**: `handler.py:28-69`; documented configuration examples in `SKILL.md:20-46` and `README.md:49-57` **Vulnerability Type**: Plaintext credential storage and overbroad configuration-file access **Risk Level**: High ### Vulnerable Code ```python env_host = os.environ.get('MIKROTIK_HOST') env_user = os.environ.get('MIKROTIK_USER', 'admin') env_pass = os.environ.get('MIKROTIK_PASS', '') if env_host: devices['default'] = { 'host': env_host, 'username': env_user, 'password': env_pass } tools_md_path = os.path.expanduser('~/.openclaw/workspace/TOOLS.md') if os.path.exists(tools_md_path): try: with open(tools_md_path, 'r', encoding='utf-8') as f: content = f.read() mikrotik_section = re.search( r'###\s*MikroTik 设备.*?\n(.*?)(?=\n###|\Z)', content, re.DOTALL | re.IGNORECASE ) if mikrotik_section: section_text = mikrotik_section.group(1) device_pattern = ( r'-\s*\*\*([^*]+)\*\*[::]\s*' r'([^,\n]+),\s*([^,\n]+),\s*(.+?)\s*$' ) matches = re.findall( device_pattern, section_text, re.MULTILINE ) for name, host, username, password in matches: device_key = name.strip().lower() pwd = password.strip() if pwd.lower() in ['空密码', '无密码', 'none', 'null', '']: pwd = '' devices[device_key] = { 'host': host.strip(), 'username': username.strip(), 'password': pwd } ``` The setup documentation instructs users to place credentials directly in the shared Markdown file: ```markdown ### MikroTik devices - **office**: 192.168.1.1, admin, empty password - **home**: 192.168.88.1, admin, yourpassword ``` ### Technical An ...[truncated 1597 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove support for literal passwords in `TOOLS.md`. 2. Store only opaque secret references, such as `secret://mikrotik/office`, in workspace configuration. 3. Retrieve credentials at runtime from an OS keyring, Vault, cloud secret manager, or equivalent protected service. 4. Use a dedicated configuration file containing only MikroTik metadata rather than reading the entire global workspace document. 5. Enforce restrictive file ownership and permissions for any local configuration containing sensitive metadata. 6. Redact credentials from diagnostics, exceptions, logs, and serialized state. 7. Use separate, least-privileged RouterOS accounts for each managed device and rotate existing credentials after migration. 8. Update all setup documentation so secure secret storage is the only recommended workflow. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
mikrotik-api/client.py:14
Finding
Router Administrator Credentials Transmitted Through an Unencrypted Management Protocol<![CDATA[ ## Vulnerability Details **File Location**: `mikrotik-api/client.py:14-40` and `mikrotik-api/client.py:216-229` **Vulnerability Type**: Cleartext transmission of management credentials **Risk Level**: Critical ### Vulnerable Code ```python def __init__(self, host: str, username: str = 'admin', password: str = '', port: int = 8728, timeout: int = 5): self.host = host self.port = port self.username = username self.password = password self.timeout = timeout self.sock: Optional[socket.socket] = None self.connected = False def connect(self) -> bool: try: self.sock = socket.create_connection( (self.host, self.port), timeout=self.timeout ) self.sock.setblocking(0) self.connected = True return True except Exception as e: print(f"Connection failed: {e}") return False ``` ```python def login(self) -> bool: if not self.sock: return False try: self._send_word('/login') self._send_word(f'=name={self.username}') self._send_word(f'=password={self.password}') self._send_word('') response = self._recv_response(timeout=3.0) ``` ### Technical Analysis The client defaults to RouterOS API port 8728 and creates a raw TCP socket. It does not wrap that socket in TLS and does not perform certificate or hostname verification. The username and password are then transmitted as RouterOS API words over this unencrypted connection. Although the scanner checks whether port 8729 is open, the management client contains no TLS implementation for API-SSL. Merely changing the port to 8729 would not be sufficient because TLS negotiation and certificate validation are absent. An attacker able to observe or alter traffic on the local network can intercept credentials and management responses or manipulate unauthenticated transport data. ### Attack Path 1. The user configures valid RouterOS administ ...[truncated 947 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Implement RouterOS API-SSL using Python's `ssl` module and default to port 8729. 2. Build the TLS context with `ssl.create_default_context()` and require certificate-chain validation. 3. Verify the expected hostname or device identity and support a user-configured private CA for internally issued certificates. 4. Do not silently fall back from TLS to plaintext. 5. Reject port 8728 by default. If legacy plaintext access is retained, require a prominent, explicit, per-connection override limited to an isolated management network. 6. Consider certificate or public-key pinning for high-value network infrastructure. 7. Use a dedicated management VLAN and restrict API access at the router firewall. 8. Rotate all credentials previously used over plaintext connections. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
handler.py:1237
Finding
Unrestricted Privileged RouterOS Command Execution Without Safety Controls<![CDATA[ ## Vulnerability Details **File Location**: `handler.py:1237-1250`; related CLI path at `mikrotik-api/cli.py:119-127` **Vulnerability Type**: Arbitrary privileged management-command execution **Risk Level**: High ### Vulnerable Code ```python elif 'scan' in command.lower() or '扫描' in command.lower(): result = format_scan(api, quick) else: results = api.run_command(command) if results: result = "Command result:\n" for item in results: for key, value in item.items(): result += f" {key}: {value}\n" else: result = "(no result)" ``` The command-line interface exposes the same unrestricted primitive: ```python elif args.command == 'cmd': if not args.args: print("A command path is required") sys.exit(1) cmd = args.args[0] results = api.run_command(cmd) ``` The command wrapper also includes destructive operations: ```python def reboot(self): self.api.run_command('/system/reboot') def shutdown(self): self.api.run_command('/system/shutdown') ``` ### Technical Analysis Commands that do not match a predefined display action are forwarded directly to `api.run_command()`. There is no read-only allowlist, mutation detection, destructive-command denylist, argument validation, privilege separation, approval workflow, or confirmation prompt. RouterOS command paths can perform substantially more than information retrieval. Depending on the configured account permissions, commands can add or remove firewall rules, routes, users, scripts, scheduler entries, interfaces, VPN peers, and files. They may also reboot or shut down the router. This is not operating-system shell injection because the value is transmitted through the RouterOS API protocol. It is nevertheless an arbitrary privileged command-execution interface against critical network infrastructure. ### Attack Path 1. The Skill is configured with a RouterOS account that has administrative or policy- ...[truncated 1176 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove arbitrary command forwarding from the default Skill interface. 2. Create a strict allowlist of required read-only RouterOS command paths, preferably limited to `/print` operations with controlled arguments. 3. Reject commands that add, set, enable, disable, remove, reset, import, execute, reboot, or shut down resources. 4. Parse commands structurally rather than using substring matching. 5. Use a dedicated RouterOS account whose policy permits only the exact read operations required by the Skill. 6. Place all state-changing operations behind a separate capability that requires explicit human confirmation immediately before execution. 7. Show the exact device, command, arguments, and expected effect in the confirmation prompt. 8. Record tamper-resistant audit logs for privileged requests and outcomes. 9. Add unit and integration tests proving that destructive and unrecognized commands are rejected. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
mikrotik-api/cli.py:27
Finding
Router Password Accepted Through Process Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `mikrotik-api/cli.py:27-32` **Vulnerability Type**: Credential exposure through process arguments and shell history **Risk Level**: Medium ### Vulnerable Code ```python parser = argparse.ArgumentParser( description='MikroTik RouterOS API command-line tool' ) parser.add_argument('host', help='RouterOS device IP address') parser.add_argument( '-u', '--username', default='admin', help='Username' ) parser.add_argument( '-p', '--password', default='', help='Password' ) parser.add_argument( '--port', type=int, default=8728, help='API port' ) ``` ### Technical Analysis The CLI accepts the router password through `-p` or `--password`. Command-line arguments may be recorded in shell history, terminal session logs, automation output, crash reports, job definitions, and monitoring systems. On some systems, they are also visible to other local users through process-inspection interfaces while the command is running. The password is therefore exposed outside the intended client process before it is used for authentication. ### Attack Path 1. A user runs the CLI with `--password` or `-p`. 2. The complete command is saved in shell history or an automation log, or is temporarily visible in process metadata. 3. Another local user, process, support operator, or log consumer reads the command. 4. The attacker recovers the RouterOS password. 5. The attacker authenticates to the router through an exposed management service. ### Impact Assessment The obtained privileges are those of the exposed RouterOS account. If the common `admin` account is used, compromise may provide full control over firewall rules, routes, VPNs, user accounts, scripts, services, and device availability. The exposure can persist long after the CLI process exits because shell histories and centralized logs are durable. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `--password` command-line option. 2. Prompt interactively with `getpass.getpass()` when no protected credential source is configured. 3. Support OS keyrings or secret-manager references for noninteractive operation. 4. If file-based input is unavoidable, read from a protected file descriptor or a file with strictly validated ownership and permissions. 5. Ensure the password is never printed in help examples, diagnostics, process titles, or logs. 6. Update documentation and automation examples to avoid embedding secrets in command lines. 7. Rotate passwords that may previously have been supplied through argv and retained in history or logs. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (45)

Missing User Warnings

High
Confidence
98% confidence
Finding
The README explicitly tells users to give router usernames and passwords to the AI and states that the configuration will be saved to `TOOLS.md`, but it does not clearly warn that this results in persistent plaintext credential storage. Router admin credentials are highly sensitive; exposing them can allow full device takeover, firewall/routing changes, traffic interception, or lateral movement across the local network.

Ssd 3

High
Confidence
99% confidence
Finding
The instructions direct users to provide router credentials to the AI and persist them in a tool file, creating a direct secret-handling vulnerability. In the context of a router-management skill, these credentials are especially dangerous because compromise enables administrative control over network edge devices, traffic policy, VPNs, and potentially downstream systems.

Missing User Warnings

High
Confidence
99% confidence
Finding
The manual configuration example embeds device names, IPs, usernames, and passwords directly in `TOOLS.md`, normalizing plaintext storage of infrastructure credentials. If that file is read by other tools, checked into repositories, synced, or exposed through the agent workspace, attackers gain privileged access to routers and potentially the entire managed network.

Ssd 3

High
Confidence
99% confidence
Finding
The example encourages users to store MikroTik credentials in plaintext within `~/.openclaw/workspace/TOOLS.md`, a location likely accessible to the agent and potentially other processes, backups, or version control. This materially increases the chance of credential leakage and subsequent unauthorized access to network infrastructure.

Ssd 3

High
Confidence
99% confidence
Finding
This section repeats the unsafe pattern of placing sensitive router login details in a plaintext shared file, reinforcing insecure operator behavior. Repetition in setup guidance makes accidental credential exposure more likely and broadens attack surface through logs, screenshots, sync tools, or agent-readable workspace content.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This skill context is especially dangerous because it targets network infrastructure and the documentation indicates active subnet scanning, local network inspection, API port probing, and even attempts to log in with the default admin account and empty password. In an enterprise or production environment, that crosses from administration into intrusive discovery and potentially unauthorized access behavior, which can trigger alerts or compromise weakly configured devices.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
This skill context is especially dangerous because it targets network infrastructure and the documentation indicates active subnet scanning, local network inspection, API port probing, and even attempts to log in with the default admin account and empty password. In an enterprise or production environment, that crosses from administration into intrusive discovery and potentially unauthorized access behavior, which can trigger alerts or compromise weakly configured devices.

Missing User Warnings

High
Confidence
96% confidence
Finding
Wireless client enumeration exposes MAC addresses, IPs, SSIDs, signal metrics, uptime, and traffic statistics for connected clients. This is sensitive endpoint and usage data that can reveal user presence, device identity, and network behavior, creating privacy and operational security risks if shown without explicit warning or authorization.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The skill includes an active local-network scanning capability (`MikroTikScanner.scan()`) that operates independently of configured target devices. This exceeds the stated purpose of connecting to and managing specified MikroTik devices and enables reconnaissance of the broader environment, which could expose unauthorized assets and expand attack surface knowledge.

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill directly executes user-supplied RouterOS commands on the target device, enabling arbitrary remote administrative actions. Because there is no safety interlock, allowlist, or high-risk-operation confirmation, a user prompt or downstream agent misuse could disable protections, alter routing/firewall state, create accounts, or otherwise compromise the router.

Missing User Warnings

High
Confidence
98% confidence
Finding
The `shutdown()` method immediately powers down the device without any safeguard. For an infrastructure device, shutdown is more disruptive than read operations and can cause prolonged outage until manual intervention restores service, making accidental or unauthorized use particularly damaging.

Context-Inappropriate Capability

High
Confidence
100% confidence
Finding
The code attempts to log into discovered devices using the username 'admin' with an empty password. This is dangerous because it operationalizes default-credential probing against network devices, which can lead to unauthorized access, violate policy, and normalize credential abuse even if intended for convenience.

Missing User Warnings

High
Confidence
99% confidence
Finding
Attempting 'admin' with a blank password against discovered devices without prominent user notice is an unsafe authentication probe. In this skill context, it materially increases danger because the feature is embedded in a device-management tool where users may not realize it is performing credential attacks rather than just connecting to known equipment.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The scanner performs broad active discovery across local subnets and, for matching devices, escalates to connection and authentication attempts. That goes beyond passive device management and creates potentially unauthorized reconnaissance and access behavior on the user's network, especially dangerous in an agent skill that may be run with little scrutiny.

Natural-Language Policy Violations

Medium
Confidence
82% confidence
Finding
Nearly all user-facing instructions, examples, and invocation phrases are provided only in Chinese, including the explicit spoken passphrase and command examples. Under the stated policy, forcing a specific language without opt-in or documented justification is a natural-language policy concern.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
Advertising automatic LAN scanning 'without configuration' encourages active probing of the local network without clearly warning users that device discovery may reveal host/IP/MAC information and may be unauthorized in some environments. In a network-management skill, scanning is contextually relevant, but silent or under-warned probing can still create privacy, policy, and detection risks.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill advertises capabilities that involve reading local files, consuming environment variables, and invoking shell-backed functionality, but it does not declare any explicit tool scope or permissions boundaries. This creates a transparency and least-privilege problem: an agent or user may invoke the skill without realizing it can access credentials, local configuration, and perform host/network actions.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The configuration section encourages storing router credentials in TOOLS.md and environment variables before presenting strong warnings, which normalizes insecure handling of high-value administrative secrets. Given the skill manages routers and supports custom commands, exposed credentials could directly enable device compromise or broader network access.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The trigger phrases are broad enough to match ordinary troubleshooting requests, increasing the chance of unintentional invocation of a privileged network-management skill. In this context, accidental activation is risky because the skill can access router state, credentials, and potentially execute commands against infrastructure devices.

Vague Triggers

Medium
Confidence
95% confidence
Finding
Generic examples for backup, cleanup, API configuration, and scanning increase the likelihood that destructive or sensitive operations are triggered from ambiguous natural-language requests. Because these actions can alter device state, expose management interfaces, or enumerate networks, accidental matching has real operational and security consequences.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The user/account display functionality reveals potentially sensitive administrative information, including usernames and service exposure, without any privacy notice or minimization. Such data can help an attacker identify privileged accounts, enabled services, and management interfaces for follow-on attacks.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
DHCP lease output reveals client IP addresses, MAC addresses, hostnames, and statuses without any warning or access control. This inventory data is highly useful for mapping internal endpoints and can expose personal or business-sensitive device information.

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
The implementation exposes extensive topology and infrastructure data such as neighbors, active connections, routing peers, wireless clients, DHCP leases, ARP tables, and scheduler contents. While some of this may aid administration, aggregating and displaying this breadth of reconnaissance data goes beyond a narrow device-management scope and can materially assist lateral movement or targeting if misused.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill performs active network scanning without an explicit user-facing warning that it will probe the local network. In managed or sensitive environments, such probing can violate policy, trigger monitoring alerts, or enumerate assets the user did not intend to inspect.

Static analysis

No suspicious patterns detected.