Back to skill

Security audit

MikroTik API

Security checks for vulnerabilities and agentic risk

Overview

This skill is purpose-built for MikroTik router administration, but its examples use unsafe connection and installation defaults that could expose router credentials or affect sensitive infrastructure.

Review before installing. Use this only with a least-privilege MikroTik account, prefer TLS on port 8729 with certificate and hostname verification enabled, avoid curl commands that place passwords on the command line, and install dependencies in an isolated virtual environment rather than modifying system Python.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:37
Finding
Router Credentials and Administrative Traffic Transmitted over an Unencrypted API Connection<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 37-47 **Vulnerability Type**: Plaintext transmission of sensitive credentials and administrative traffic **Risk Level**: High ### Vulnerable Code ```python conn = routeros_api.RouterOsApiPool( host=host, username=username, password=password, plaintext_login=True, # Required for RouterOS 6.43+ port=8728 # Use 8729 for SSL ) api = conn.get_api() # ... do work ... conn.disconnect() ``` ### Technical Analysis The primary connection example uses RouterOS API port 8728 without transport encryption. The `plaintext_login=True` setting does not itself require an unencrypted transport, but combining it with port 8728 means that credentials and subsequent privileged RouterOS API traffic can traverse the network without TLS protection. Because this Skill is intended to perform sensitive router-management operations, intercepted traffic may contain administrator credentials, network topology, firewall policy, VPN configuration, user information, and configuration commands. An on-path attacker may also be able to alter requests or responses. The connection is necessary for the declared router-management functionality, but an unencrypted connection is not the minimum-risk implementation. TLS on port 8729 should be the default. ### Attack Path 1. A user or Agent follows the documented default connection example. 2. The Agent reads the router username and password from environment variables or user input. 3. The Agent connects to the router over the unencrypted RouterOS API port 8728. 4. An attacker positioned on the same network segment, a compromised gateway, or another on-path location captures or modifies the API traffic. 5. The attacker recovers reusable router credentials or modifies administrative commands. 6. The attacker authenticates to the router and performs operations permitted by the compromised account. ### Impact Assessment If a privileged RouterO ...[truncated 614 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make TLS-protected RouterOS API port 8729 the mandatory default. 2. Remove port 8728 from general-purpose examples or clearly restrict it to explicitly approved, isolated test environments. 3. Require certificate and hostname verification. 4. Refuse to transmit credentials when transport encryption is unavailable unless the user explicitly acknowledges the risk. 5. Use a dedicated RouterOS account with only the policy permissions needed for the requested operation. 6. Avoid broad administrator accounts for monitoring or read-only tasks. 7. Document secure certificate provisioning and trust-store configuration. 8. Ensure connections are always terminated in a `finally` block or context manager. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:55
Finding
TLS Certificate and Hostname Verification Disabled for Router Management Connections<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 55-64 and 488-527 **Vulnerability Type**: Missing TLS peer authentication **Risk Level**: High ### Vulnerable Code RouterOS API TLS example: ```python conn = routeros_api.RouterOsApiPool( host=host, username=username, password=password, plaintext_login=True, use_ssl=True, ssl_verify=False, # Set True with proper certs ssl_verify_hostname=False, port=8729 ) ``` REST API curl example: ```bash curl -k -u user:pass https://<IP>/rest/ip/address ``` REST API Python examples: ```python import requests from requests.auth import HTTPBasicAuth base = 'https://<IP>/rest' auth = HTTPBasicAuth('<USER>', '<PASS>') # GET all interfaces r = requests.get(f'{base}/interface', auth=auth, verify=False) print(r.json()) # POST (run commands with parameters) r = requests.post(f'{base}/ip/address/print', auth=auth, verify=False, json={'_proplist': ['address', 'interface']}) print(r.json()) ``` ### Technical Analysis All documented TLS connection methods disable certificate validation: - `ssl_verify=False` disables certificate-chain verification. - `ssl_verify_hostname=False` disables validation that the certificate belongs to the intended router. - `curl -k` accepts invalid and untrusted certificates. - `requests(..., verify=False)` disables certificate verification in Python. TLS encryption without peer authentication does not establish that the endpoint is the intended router. An attacker able to intercept routing, DNS, ARP, Wi-Fi, or gateway traffic can present an arbitrary certificate and impersonate the router. Because the client accepts that certificate, the attacker can terminate TLS, inspect credentials and requests, and establish a separate connection to the real router. The network connection itself is required for the declared functionality, but disabling authentication of the remote endpoint is unnecessary and exposes highly privileged operati ...[truncated 1463 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Set `ssl_verify=True` and enable hostname verification in the RouterOS API connection. 2. Remove `-k` from all curl commands. 3. Remove `verify=False` from all Python Requests calls. 4. Provision each router with a certificate issued by a trusted internal or public certificate authority. 5. Connect using a hostname or IP address included in the certificate's Subject Alternative Name. 6. Configure the client to trust the appropriate internal CA where private infrastructure is used. 7. Where CA-based verification is not practical, pin a reviewed router certificate or public-key fingerprint and fail closed on mismatch. 8. Do not silently fall back to insecure TLS or plaintext connections. 9. Add explicit error handling for certificate expiration, hostname mismatch, and untrusted issuers. 10. Rotate router credentials if they have previously been used with these insecure examples over an untrusted network. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:488
Finding
Router Passwords Embedded in Curl Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 488-507 **Vulnerability Type**: Sensitive credential exposure through command-line arguments and shell history **Risk Level**: Medium ### Vulnerable Code ```bash # GET - Read resources curl -k -u user:pass https://<IP>/rest/ip/address # PUT - Create new entry curl -k -u user:pass -X PUT https://<IP>/rest/ip/address \ --data '{"address":"192.168.1.1/24","interface":"ether1"}' \ -H "content-type: application/json" # PATCH - Update entry curl -k -u user:pass -X PATCH https://<IP>/rest/ip/address/*1 \ --data '{"comment":"updated"}' -H "content-type: application/json" # DELETE - Remove entry curl -k -u user:pass -X DELETE https://<IP>/rest/ip/address/*1 # POST - Run any command curl -k -u user:pass -X POST https://<IP>/rest/ip/address/print \ --data '{"_proplist":["address","interface"]}' \ -H "content-type: application/json" ``` ### Technical Analysis The examples place the username and password directly in the curl `-u` argument. When users replace `user:pass` with real credentials, the password may be retained or exposed through: - Interactive shell history. - Process command-line inspection. - Terminal session recording. - CI/CD logs and Agent execution traces. - Monitoring, auditing, or endpoint telemetry. - Copied command transcripts and support records. Although some curl implementations may attempt to obscure credentials in process listings after startup, this behavior is not a reliable security boundary and does not protect shell history or execution logs. ### Attack Path 1. A user or Agent copies a documented curl command. 2. The placeholder is replaced with a valid RouterOS username and password. 3. The command is executed in a shell or automated environment. 4. The complete command is saved in shell history, an Agent transcript, process telemetry, or a CI log. 5. A local user, log reader, support operator, or attacker with access to those records retrieves the cr ...[truncated 618 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not include passwords directly in command-line arguments. 2. Use `curl -u username` without appending the password so curl prompts for it interactively. 3. For automation, use a protected curl configuration file or `.netrc` file with restrictive file permissions. 4. Prefer an operating-system credential store or approved secret-management service. 5. Prevent secret values from being written to Agent transcripts, CI logs, debugging output, or command history. 6. Use dedicated, least-privilege RouterOS accounts rather than shared administrator credentials. 7. Rotate any passwords that may already have appeared in shell histories or retained logs. 8. Combine secure credential handling with full TLS certificate and hostname verification. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:12
Finding
Unpinned Third-Party Package Installed into the System Python Environment<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 12-15 **Vulnerability Type**: Unsafe and non-reproducible dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash pip3 install --break-system-packages routeros-api ``` ### Technical Analysis The installation instruction retrieves the current version of `routeros-api` and its transitive dependencies without pinning versions or verifying hashes. The effective code installed can therefore change after the Skill has been reviewed. The `--break-system-packages` option also overrides protections intended to prevent pip from modifying a system-managed Python environment. This can create dependency conflicts or replace packages used by unrelated system tools. No suspicious package source, typosquatted name, or confirmed malicious dependency was identified. The risk arises from mutable upstream resolution, lack of integrity pinning, and installation into the system environment rather than from evidence that the named package is malicious. ### Attack Path 1. The Agent follows the prerequisite installation command. 2. Pip resolves the latest available package and transitive dependency versions from its configured package index. 3. A compromised future release, compromised dependency, package-index account takeover, or unsafe custom index supplies malicious code. 4. Pip downloads and installs the mutable package set into the system Python environment. 5. Installation hooks or imported runtime code execute with the privileges of the Agent process. 6. Malicious code may access the Agent environment, including MikroTik credentials, or interfere with subsequent router-management operations. A separate availability path exists where incompatible dependency versions overwrite or conflict with system-managed packages, causing unrelated Python-based tools to malfunction. ### Impact Assessment If the installation is performed with elevated privileges, a compromised dependency may ex ...[truncated 533 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `--break-system-packages`. 2. Install dependencies in a dedicated virtual environment or isolated container. 3. Pin a reviewed version of `routeros-api` and all transitive dependencies. 4. Use a lock file or a requirements file containing cryptographic hashes. 5. Install only from an explicitly approved package index over authenticated TLS. 6. Review package provenance, release history, maintainers, and dependency changes before updating. 7. Use automated dependency scanning and controlled update procedures. 8. Run package installation and router-management operations with the least operating-system privilege required. 9. Keep secrets unavailable during dependency installation whenever possible. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (12)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
RouterOS 7.1+ also supports a REST API over HTTP/HTTPS. Use when the Python library is unavailable.

### REST via curl
```bash
# GET - Read resources
curl -k -u user:pass https://<IP>/rest/ip/address
Confidence
86% confidence
Finding
The documentation presents copy-pastable `curl` commands with placeholders for credentials, arbitrary REST paths, and disabled certificate checks. In a high-privilege router-management context, that combination can facilitate parameter abuse, accidental destructive operations, and credential exposure if users adapt the examples without understanding the risks.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
password=password,
    plaintext_login=True,
    use_ssl=True,
    ssl_verify=False,       # Set True with proper certs
    ssl_verify_hostname=False,
    port=8729
)
Confidence
97% confidence
Finding
Explicitly setting `ssl_verify=False` in the primary SSL example normalizes insecure transport behavior. Given the administrative power over firewall, routing, VPN, and system functions, users copying this pattern could compromise both credentials and device integrity.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
password=password,
    plaintext_login=True,
    use_ssl=True,
    ssl_verify=False,       # Set True with proper certs
    ssl_verify_hostname=False,
    port=8729
)
Confidence
97% confidence
Finding
Explicitly setting `ssl_verify=False` in the primary SSL example normalizes insecure transport behavior. Given the administrative power over firewall, routing, VPN, and system functions, users copying this pattern could compromise both credentials and device integrity.

External Transmission

Medium
Category
Data Exfiltration
Content
RouterOS 7.1+ also supports a REST API over HTTP/HTTPS. Use when the Python library is unavailable.

### REST via curl
```bash
# GET - Read resources
curl -k -u user:pass https://<IP>/rest/ip/address
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The REST examples include real credential-bearing requests while disabling TLS validation (`-k`, `verify=False`) and do not place an explicit warning immediately around those examples. That creates a meaningful risk of credential interception or man-in-the-middle attacks, especially because this skill is for managing network infrastructure and may be copied verbatim by users.

Unrestricted Tool Access

Medium
Category
Excessive Agency
Content
# DELETE - Remove entry
curl -k -u user:pass -X DELETE https://<IP>/rest/ip/address/*1

# POST - Run any command
curl -k -u user:pass -X POST https://<IP>/rest/ip/address/print \
  --data '{"_proplist":["address","interface"]}' \
  -H "content-type: application/json"
Confidence
80% confidence
Finding
Skill grants unrestricted tool access without appropriate constraints. An agent with unfettered tool access can perform arbitrary actions including file modification, network requests, and code execution.

Session Persistence

Medium
Category
Rogue Agent
Content
# POST - Run any command
curl -k -u user:pass -X POST https://<IP>/rest/ip/address/print \
  --data '{"_proplist":["address","interface"]}' \
  -H "content-type: application/json"
```
Confidence
75% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
# POST - Run any command
curl -k -u user:pass -X POST https://<IP>/rest/ip/address/print \
  --data '{"_proplist":["address","interface"]}' \
  -H "content-type: application/json"
```
Confidence
75% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Session Persistence

Medium
Category
Rogue Agent
Content
# POST - Run any command
curl -k -u user:pass -X POST https://<IP>/rest/ip/address/print \
  --data '{"_proplist":["address","interface"]}' \
  -H "content-type: application/json"
```
Confidence
75% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
auth = HTTPBasicAuth('<USER>', '<PASS>')

# GET all interfaces
r = requests.get(f'{base}/interface', auth=auth, verify=False)
print(r.json())

# POST (run commands with parameters)
Confidence
96% confidence
Finding
The Python REST example uses `verify=False`, which disables server certificate validation and exposes Basic Auth credentials to interception by a man-in-the-middle. In a router administration skill, users may run these examples against sensitive infrastructure, raising the practical risk.

External Transmission

Medium
Category
Data Exfiltration
Content
print(r.json())

# POST (run commands with parameters)
r = requests.post(f'{base}/ip/address/print',
    auth=auth, verify=False,
    json={'_proplist': ['address', 'interface']})
print(r.json())
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
# POST (run commands with parameters)
r = requests.post(f'{base}/ip/address/print',
    auth=auth, verify=False,
    json={'_proplist': ['address', 'interface']})
print(r.json())
```
Confidence
96% confidence
Finding
This POST example again disables TLS verification while sending authenticated management traffic. Since POST requests may trigger administrative actions, exploitation via MITM could expose credentials and manipulate or observe sensitive operations.

Static analysis

No suspicious patterns detected.