Back to skill

Security audit

Asus Router

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent Asus router management tool, but it defaults high-privilege router administration to unencrypted local HTTP.

Review before installing. Use a dedicated virtual environment, pin dependencies where possible, keep config.yaml out of source control with restrictive permissions, prefer environment or secret-store credentials, and enable HTTPS on the router before using commands that read router data or reboot the device.

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 (2)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:14
Finding

Unpinned Third-Party Dependencies Create a Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:14-18
Vulnerability Type: Unpinned runtime dependencies from a public package repository
Risk Level: Medium

Vulnerable Code Snippet:

markdown
### 1. Install dependencies
```bash
pip install asusrouter aiohttp
text

### Technical Analysis

The documented installation command retrieves the latest available versions of `asusrouter` and `aiohttp` without version constraints, integrity hashes, or a reviewed lock file. Consequently, the code installed and executed by users can change after the Skill itself has been audited.

Python packages can execute code during installation and whenever imported. In this project, both dependencies are imported at module scope in `router.py`, meaning a compromised dependency release would run in the context of the user invoking the Skill. The audit found no evidence that the named dependencies are currently malicious; the issue is the absence of controls that ensure users receive the versions that were reviewed and tested.

### Attack Path

1. An attacker compromises a dependency publisher account, package release process, or package-distribution channel.
2. The attacker publishes a malicious or backdoored release under one of the dependency names.
3. A user follows the documented `pip install asusrouter aiohttp` instruction.
4. `pip` resolves the unpinned dependency to the malicious release.
5. Malicious code executes during package installation or when `router.py` imports the package.
6. The payload operates with the privileges and data access of the user running the Skill.

### Impact Assessment

Successful exploitation could provide arbitrary code execution under the invoking user's operating-system account. The exposed scope could include files readable by that account, environment variables, the plaintext router configuration, router administrator credentials, and network access available from the host. If inst
...[truncated 210 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin every direct dependency to a reviewed version rather than installing the latest release:
    text
    asusrouter==REVIEWED_VERSION
    aiohttp==REVIEWED_VERSION
    PyYAML==REVIEWED_VERSION
    
  2. Generate and commit a lock file containing resolved transitive dependencies.
  3. Require package hashes, for example by using a hash-locked requirements file and:
    bash
    python3 -m pip install --require-hashes -r requirements.txt
    
  4. Review and update pinned versions through a controlled dependency-update process.
  5. Run dependency vulnerability and provenance checks in continuous integration.
  6. Install dependencies inside a dedicated virtual environment using a non-privileged account.
  7. Ensure documentation references the locked installation procedure rather than unconstrained package names.

T09 · Insecure Skill Coding Practices

Error
Location
config.example.yaml:6
Finding

Privileged Router Administration Defaults to Unencrypted HTTP

Content
View full analysis

Vulnerability Details

File Location: config.example.yaml:6-10, router.py:21-29, router.py:78-90, SKILL.md:125-127
Vulnerability Type: Insecure default transport for sensitive router-management traffic
Risk Level: High

Vulnerable Code Snippets:

config.example.yaml:6-10

yaml
router:
  host: "192.168.1.1"        # Your router's IP address
  username: "admin"           # Router admin username
  password: "YOUR_PASSWORD"   # Router admin password
  ssl: false                  # Set true if your router uses HTTPS

router.py:21-29

python
config = {
    "router": {
        "host": os.environ.get("ASUS_ROUTER_HOST", "192.168.1.1"),
        "username": os.environ.get("ASUS_ROUTER_USER", "admin"),
        "password": os.environ.get("ASUS_ROUTER_PASS", ""),
        "ssl": False,
        "port": None,
    },

router.py:78-90

python
async def get_router():
    session = aiohttp.ClientSession()
    router = AsusRouter(
        hostname=CONFIG["router"]["host"],
        username=CONFIG["router"]["username"],
        password=CONFIG["router"]["password"],
        port=CONFIG["router"].get("port"),
        use_ssl=CONFIG["router"].get("ssl", False),
        session=session,
    )
    await router.async_connect()
    return router, session

SKILL.md:125-127

markdown
For modern routers, prefer HTTPS local access when stable: enable it in AsusWRT under **Administration → System → Local Access Config → Authentication Method**, then set `ssl: true` and the configured port.

Technical Analysis

Both the built-in configuration and the distributed example set ssl to false. The connection function passes that value directly to the router client as use_ssl, so users who retain the documented default perform privileged router administration without TLS.

The router username, password, authentication exchange, API responses, and ...[truncated 2397 chars]

Remediation
View remediation

Remediation Suggestions

  1. Change the built-in and example defaults to TLS:
    yaml
    router:
      host: "192.168.1.1"
      username: "admin"
      password: "YOUR_PASSWORD"
      ssl: true
      port: 8443
    
  2. Refuse non-TLS connections by default. If legacy HTTP support is required, require an explicit option such as allow_insecure_http: true.
  3. Display a prominent warning whenever insecure HTTP is enabled, including the risk to administrator credentials and management traffic.
  4. Ensure HTTPS certificate verification is enabled. Provide a documented method to trust a router-specific certificate or local certificate authority rather than silently disabling verification.
  5. Prefer a dedicated router account with only the minimum permissions required, if the firmware supports role separation.
  6. Avoid storing the administrator password in a broadly readable plaintext file. Use restrictive file permissions and consider an operating-system credential store or injected secret.
  7. Update setup documentation so HTTPS is mandatory where supported, with HTTP documented only as a legacy compatibility exception.
  8. Consider blocking destructive commands such as reboot when insecure transport is in use.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (6)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill clearly relies on shell, file access, environment/dependency usage, and network access to contact the router, but it does not declare any explicit tool scope or permissions boundary. In an agent environment, missing scope declarations can lead to over-broad execution privileges and make it harder to audit or constrain what the skill is allowed to do, especially since it can read credentials from local files and issue router-management actions such as reboot.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The presence-detection command reveals occupancy-related information about named individuals or devices on the local network, which is sensitive personal data. In the context of a router-management skill, this capability is expected, but exposing it without an explicit privacy notice, access controls, or output minimization increases the risk of misuse by an unauthorized local user or downstream caller.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · router.py (reported line 408)May include surrounding context.

python
print("🏓 Network latency check\n")
    for name, ip in targets:
        try:
            result = subprocess.run(
                ['ping', '-c', '3', '-W', '2', ip],
                capture_output=True, text=True, timeout=10
            )

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill instructs users to place router admin credentials in config.yaml but does not warn about secure storage, file permissions, or alternatives such as secrets management. Because these are high-value administrative credentials for network infrastructure, accidental exposure through backups, source control, logs, or permissive filesystem access could allow compromise of the router and the local network.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code accesses sensitive environment variables for the router host, username, and password, including the password variable. While the module docstring mentions configuration generally, it does not clearly disclose that credentials will be read from environment variables, which is one of the safety-relevant operations called out for code files.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · router.py (reported line 562)May include surrounding context.

python
return
    router, session = await get_router()
    try:
        data = await safe_get(router, getattr(AsusData, name))
        print(json.dumps(data, indent=2, default=json_default))
    finally:
        await close(router, session)

Static analysis

No suspicious patterns detected.