Back to skill

Security audit

Imou Open Device Video

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its Imou camera-video purpose, but it can send sensitive camera tokens and device metadata to any configured API base URL, so it needs review before installation.

Install only if you trust the publisher and will set IMOU_BASE_URL to one of the official HTTPS Imou/Lechange endpoints listed in the skill. Treat the Imou app credentials and returned HLS URLs as sensitive camera access material, and prefer a pinned or locked requests installation before use.

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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/imou_client.py:22
Finding

Unrestricted API Base URL Can Redirect Sensitive Requests to an Arbitrary Server

Content
View full analysis

Vulnerability Details

File Location: scripts/imou_client.py:22-23, 40-62; related configuration flow in scripts/device_video.py:27-28 and documentation in SKILL.md:43-57, 109-113
Vulnerability Type: Unvalidated sensitive-data destination
Risk Level: High

Complete Code Snippet

python
def _get_base_url():
    return os.environ.get("IMOU_BASE_URL", "").strip() or DEFAULT_BASE_URL
python
def _request(method: str, params: dict, app_id: str, app_secret: str, base_url: str = None) -> dict:
    """
    Send one Open API request.
    :param method: API method name (e.g. 'accessToken', 'bindDeviceLive').
    :param params: Request params object.
    :param app_id: App ID.
    :param app_secret: App secret for sign.
    :param base_url: Optional base URL; uses env IMOU_BASE_URL or default if None.
    :return: Full response body as dict; check result.code for '0'.
    """
    base = base_url or _get_base_url()
    url = f"{base.rstrip('/')}/openapi/{method}"
    time_sec = int(time.time())
    nonce = uuid.uuid4().hex
    sign = _build_sign(time_sec, nonce, app_secret)
    body = {
        "system": {
            "ver": "1.0",
            "appId": app_id,
            "sign": sign,
            "time": time_sec,
            "nonce": nonce,
        },
        "id": str(uuid.uuid4()),
        "params": params,
    }
    headers = {
        "Content-Type": "application/json",
        OPENCLAW_HEADER: OPENCLAW_HEADER_VALUE,
    }
    resp = requests.post(url, headers=headers, json=body, timeout=30)
    resp.raise_for_status()
    return resp.json()

The CLI also passes the environment-controlled value directly into every request:

python
APP_ID = os.environ.get("IMOU_APP_ID", "")
APP_SECRET = os.environ.get("IMOU_APP_SECRET", "")
BASE_URL = os.environ.get("IMOU_BASE_URL", "").strip() or "https://openapi.lechange.cn"

Technical A

...[truncated 3172 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse the configured URL with urllib.parse.urlparse.
  2. Require the https scheme and reject HTTP, protocol-relative URLs, fragments, query strings, and embedded username/password components.
  3. Allowlist the documented Imou API hosts:
    • openapi.lechange.cn
    • openapi-sg.easy4ip.com
    • openapi-fk.easy4ip.com
    • openapi-or.easy4ip.com
  4. Validate ports, permitting only the expected HTTPS port where an explicit port is present.
  5. Reject unexpected base paths rather than concatenating /openapi/{method} onto an arbitrary path.
  6. If private or test endpoints are operationally necessary, require a separate explicit unsafe-development option and display a prominent warning before transmitting credentials.
  7. Keep TLS certificate verification enabled and consider using a dedicated requests.Session with a narrowly scoped adapter or destination policy.
  8. Update SKILL.md to state that the plaintext appSecret is used locally to derive a signature rather than directly sent, while clearly listing all other transmitted sensitive fields.
  9. Add automated tests covering HTTP URLs, unknown hosts, embedded credentials, malformed ports, and unexpected paths.

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned Third-Party Dependency Creates a Non-Reproducible Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1; related installation instructions in SKILL.md:14-18, 36-39
Vulnerability Type: Unpinned dependency installation
Risk Level: Medium

Complete Code Snippet

requirements.txt contains:

text
requests>=2.28.0

The installation instructions use an unconstrained package installation:

bash
pip install requests

Technical Analysis

The dependency declaration sets only a minimum version and has no upper bound, exact version, lock file, or package hash. The documented installation command is even less constrained and installs whichever version the active package index currently resolves.

The requests package is legitimate and necessary for the declared API functionality; no evidence of typosquatting or an intentionally malicious dependency was found. However, this installation method is not reproducible and implicitly trusts future releases and the user's configured package index.

If a package index, mirror, local pip configuration, or future dependency release is compromised, installation may retrieve code that was never reviewed as part of this Skill audit. Python packages can execute code during installation and later when imported by scripts/imou_client.py.

Attack Path

  1. A user follows SKILL.md and executes pip install requests, or installs from requirements.txt.
  2. Pip resolves the dependency through the user's configured package index or mirror.
  3. Because no exact version or hash is enforced, pip accepts any qualifying current or future release.
  4. A compromised index, mirror, release, or dependency-resolution environment supplies altered package content.
  5. The package executes during installation or when imou_client.py imports requests.
  6. Malicious package code then runs with the privileges of the user installing or invoking the Skill.

Impact Assessment

Successful supply-chain exploita ...[truncated 448 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin requests to a reviewed exact version instead of using a lower-bound-only constraint.
  2. Generate a lock file containing hashes for requests and all transitive dependencies.
  3. Install with hash enforcement, such as pip install --require-hashes -r requirements.txt.
  4. Update SKILL.md to instruct users to install from the locked requirements file rather than running an unconstrained pip install requests.
  5. Document use of the official Python Package Index or an organization-controlled, authenticated mirror.
  6. Review and update pinned dependencies on a controlled schedule so security patches can be adopted without silently accepting unrelated future versions.
  7. Run dependency vulnerability and integrity checks in CI whenever the lock file changes.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares use of environment variables and network access in metadata, but it does not define an explicit tool scope such as permissions or allowed-tools. That creates an authorization gap where a runtime or reviewer cannot easily verify or constrain what external access the skill is expected to have, increasing the risk of over-broad execution and secret exposure if the skill is invoked in a permissive environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module docstring explicitly states that all descriptions and output are in English. This is a natural-language locale policy constraint presented without offering the user any language choice or documenting a justified region-specific need.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
87% confidence
Finding

The client allows the destination API host to be overridden via IMOU_BASE_URL or a base_url parameter, then transmits access tokens, device IDs, and signed requests to that host without validation. If an attacker can influence configuration or caller input, secrets and surveillance metadata could be exfiltrated to an arbitrary server, and the skill context makes this more sensitive because it handles camera/video access data.

Content

Scanner excerpt · scripts/imou_client.py (reported line 63)May include surrounding context.

python
"Content-Type": "application/json",
        OPENCLAW_HEADER: OPENCLAW_HEADER_VALUE,
    }
    resp = requests.post(url, headers=headers, json=body, timeout=30)
    resp.raise_for_status()
    return resp.json()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code sends request bodies containing access tokens, device identifiers, channel identifiers, and record query parameters to a remote API via requests.post. Although the module docstrings describe functionality, there is no user-facing warning, confirmation, logging, or explicit disclosure near the network transmission to indicate that user or system data is being sent off-host.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified as requests>=2.28.0, which allows installation of any later version without guaranteeing a reviewed, reproducible release. This creates supply-chain and reproducibility risk because vulnerable or behavior-changing versions could be pulled in over time, and the manifest does not constrain installs to a known-safe version.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.28.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The manifest references requests without pinning to a specific version, while the package has multiple known advisories across versions. Because the actual installed version is unverifiable from this file, environments may resolve to an affected release, making it impossible to assure that the skill avoids known issues such as credential leakage or request-handling flaws.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

Several functions implicitly read IMOU_APP_ID and IMOU_APP_SECRET from environment variables, which are sensitive credentials. The code lacks a warning, comment, or user-visible notice explaining that the skill accesses stored credentials from the environment.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.