Back to skill

Security audit

海康云眸设备控制

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Hik-Cloud device-control helper, but it needs Review because it can send cloud credentials and tokens to an unconstrained custom URL and can perform sensitive device actions without clear confirmation gates.

Review this skill before installing. Only use it with a Hik-Cloud application whose permissions are narrowly scoped, avoid custom base URLs unless you fully trust the endpoint, protect or disable the token cache where possible, and require explicit human confirmation before capture, arm/disarm, PTZ movement, OSD/time/NTP changes, or storage-card initialization.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/hik_open_device_control.py:124
Finding
Credentials and Bearer Tokens Can Be Sent to an Arbitrary or Unencrypted Origin<![CDATA[ ## Vulnerability Details **File Location**: `scripts/hik_open_device_control.py:124-127`, `scripts/hik_open_device_control.py:208-224`, and `scripts/hik_open_device_control.py:282-289` **Vulnerability Type**: Insufficient validation of a security-sensitive network destination **Risk Level**: High ### Vulnerable Code ```python def normalize_base_url(base_url: str) -> str: normalized = base_url.strip() if not normalized: raise ApiError("base URL must not be empty") return normalized.rstrip("/") ``` ```python def fetch_access_token( base_url: str, client_id: str, client_secret: str, timeout: float, ) -> dict[str, Any]: status, payload = http_json_request( method="POST", url=base_url.rstrip("/") + TOKEN_PATH, headers=None, timeout=timeout, form_body={ "client_id": client_id, "client_secret": client_secret, "grant_type": "client_credentials", "scope": "app", }, ) ``` ```python token, refreshed = resolve_access_token(base_url, timeout, cache_file, explicit_token) headers = {"Authorization": f"Bearer {token}"} status, payload = http_json_request( method=spec.method, url=spec.build_url(base_url), headers=headers, timeout=timeout, json_body=spec.json_body, ) ``` ### Technical Analysis The Skill legitimately needs to transmit OAuth client credentials to obtain an access token and then use that bearer token to invoke the declared Hik-Cloud device APIs. However, the destination is not constrained to a trusted HTTPS origin. The `normalize_base_url` function only removes whitespace and a trailing slash. It does not: - Require the `https` scheme. - Restrict the hostname to the official Hik-Cloud service or an approved allowlist. - Reject embedded URL credentials, unexpected ports, fragments, or malformed origins. - Separate the OAuth authorization server from the business API origin. - Establish a high ...[truncated 2038 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the configured base URL with `urllib.parse.urlsplit` and reject invalid or ambiguous URLs. 2. Require `https` for all credential-bearing requests. Permit plaintext HTTP only through an explicit development-only override that never uses production credentials. 3. Allowlist `api2.hik-cloud.com` by default. 4. If custom environments are required, maintain an administrator-configured allowlist of trusted hostnames or require an explicit confirmation option such as `--allow-custom-auth-origin`. 5. Reject URLs containing user information, query strings, fragments, unsupported ports, or non-origin paths. 6. Consider separate configuration for the OAuth issuer and business API, with independent allowlists. 7. Ensure authenticated requests cannot follow redirects to a different origin. Reject cross-origin redirects rather than forwarding credentials or authorization headers. 8. Add tests covering rejection of `http://`, attacker-controlled hosts, embedded credentials, malformed URLs, and cross-origin redirects. 9. Document that custom origins receive OAuth credentials and bearer tokens so operators can make an informed trust decision. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/hik_open_device_control.py:153
Finding
Bearer-Token Cache Is Written Without Explicit Restrictive Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/hik_open_device_control.py:153-155` **Vulnerability Type**: Insecure storage of authentication material **Risk Level**: Medium ### Vulnerable Code ```python def save_token_cache(cache_file: Path, payload: dict[str, Any]) -> None: cache_file.parent.mkdir(parents=True, exist_ok=True) cache_file.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8") ``` ### Technical Analysis The cache contains a reusable bearer token: ```json { "access_token": "...", "expires_in": 3600, "expires_at": 1234567890, "token_type": "bearer" } ``` The cache directory and file are created without explicit security modes. Their effective permissions depend on the process umask and any pre-existing directory or file permissions. An existing permissive file is not corrected. The write is also non-atomic and uses a caller-configurable path. The implementation does not verify that the destination is owned by the current user, is a regular file, or is not a symbolic link. These omissions can expose the bearer token to other local users or processes in shared or incorrectly configured environments. ### Attack Path 1. The Skill runs with a permissive umask, uses a permissive pre-existing cache file, or is configured to use a cache path in an unsafe directory. 2. `save_token_cache` writes the bearer token in plaintext without enforcing owner-only permissions. 3. Another local user or process reads the cache while the token remains valid. 4. The attacker extracts `access_token` and sends authenticated requests directly to the Hik-Cloud API. 5. The attacker exercises the application privileges associated with that token until it expires or is revoked. ### Impact Assessment A local attacker able to read the cache can inherit the bearer token's effective device-management privileges. Depending on the token scope, this can permit device-state queries, arm/disarm operations, PTZ control, re ...[truncated 282 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create the cache directory with owner-only mode `0700`. 2. Create cache files with mode `0600`, independent of the current umask. 3. Correct overly permissive permissions on an existing cache file before reading or writing it, or reject the file with a clear error. 4. Verify that the cache file and parent directory are owned by the current user. 5. Reject symbolic links and non-regular files. 6. Write to a securely created temporary file in the same directory, flush and optionally `fsync` it, then atomically replace the cache. 7. Avoid accepting arbitrary cache paths in privileged execution contexts, or validate that a custom path is inside an approved user-owned directory. 8. Add tests asserting `0700` directory permissions, `0600` file permissions, safe handling of existing permissive files, and rejection of symbolic-link destinations. 9. Consider using an operating-system credential store where available instead of a plaintext JSON cache. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
声明描述的是一个可执行的设备控制技能,核心能力应是与海康云眸开放平台交互并执行具体设备操作。但提供的代码块只是测试文件,作用是验证文档是否包含某些固定字符串和参考资料内容,属于文档契约/一致性检查,而非设备控制实现。其主要目的与声明明显不一致,因此构成实质性描述-行为不匹配。

Credential Access

High
Category
Privilege Escalation
Content
if status != 200 or "access_token" not in payload:
        error_code, error_message = summarize_error_payload(payload)
        raise ApiError(
            "failed to fetch access token: "
            f"http={status}, code={error_code}, message={error_message}"
        )
    expires_in = int(payload.get("expires_in", 0))
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
if status != 200 or "access_token" not in payload:
        error_code, error_message = summarize_error_payload(payload)
        raise ApiError(
            "failed to fetch access token: "
            f"http={status}, code={error_code}, message={error_message}"
        )
    expires_in = int(payload.get("expires_in", 0))
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Missing User Warnings

High
Confidence
95% confidence
Finding
The storage-init command invokes a destructive operation that can erase or reinitialize device storage without any confirmation prompt, dry-run mode, or explicit safety interlock. In this skill context, that can directly cause loss of video evidence or operational data if triggered accidentally or through misuse by an upstream agent.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill documents access to environment variables, token cache files, and external network endpoints, but does not declare any explicit tool scope such as allowed-tools or permissions. That creates an overbroad-execution risk: a host may grant more capabilities than reviewers or policy engines can easily reason about, especially since the skill can read secrets and make authenticated device-control requests.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
Remote capture can collect images from surveillance devices, creating clear privacy and compliance risk if triggered without strong user-intent verification and disclosure. In this skill, the capability is presented as a routine operation with no warning about consent, authorization, or sensitive-image handling, making misuse more likely.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill exposes destructive or high-impact operations such as storage card initialization and security-state changes without an explicit warning, confirmation step, or operator-safety guidance. In an agent setting, this increases the chance of accidental data loss, surveillance disruption, or unauthorized device reconfiguration from ambiguous user prompts.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The manifest exposes broad device-control capabilities such as arming/disarming, PTZ movement, capture, time sync, and storage initialization, but provides no explicit activation boundaries, authorization preconditions, or confirmation requirements. In a security-sensitive IoT context, vague routing criteria can cause the agent to invoke destructive or privacy-impacting actions for loosely related user requests, increasing the chance of unauthorized or unintended device operations.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The display name and short description are in Chinese, but the default prompt is hard-coded in English and does not offer a language or locale choice. This can amount to forcing a specific language behavior without explicit user opt-in.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
This markdown file describes obtaining OAuth tokens, injecting bearer tokens into business API calls, and using sensitive environment variables such as client secrets. Under the markdown-file criteria for SQP-2, the description should warn that the skill uses credentials and sends authentication data to external services, but no such warning is present.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documentation describes a remote image capture capability and notes that the returned picture URL remains valid for about two hours, but it does not warn about the privacy-sensitive nature of capturing images from devices or the risk of exposing a temporary but bearer-style image URL. In a device-control skill, this omission can lead users or downstream agents to handle captures and URLs insecurely, increasing the chance of unauthorized surveillance, data leakage, or unintended sharing of sensitive images.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This markdown file presents all operational instructions and API descriptions only in Chinese. Under the policy criteria, forcing a specific language without user opt-in or a documented justification is a natural-language policy concern.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The script persists OAuth access tokens to a predictable file under the user's home directory without setting restrictive file permissions or clearly warning the operator. If the host is multi-user, backed up centrally, or otherwise exposed, another local process or user could recover the token and use it to control cloud-connected devices until expiry.

Missing User Warnings

Low
Confidence
89% confidence
Finding
This markdown file documents commands that can move or zoom a physical camera and notes an operational constraint requiring a stop call before other direction operations. However, it presents these actions as pure interface details without any explicit user-facing warning about the effect on device state or the need to avoid unintended movement. For markdown files, omission of warnings about behaviors that may affect system integrity or connected devices is in scope.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The entire skill reference is written only in Chinese, with no indication that the user can choose another language or that the skill is intentionally limited to a Chinese-language audience. Under the policy, forcing a specific language without user opt-in is a natural-language locale violation.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Content
return

    for method_name in ("SetConsoleOutputCP", "SetConsoleCP"):
        method = getattr(kernel32, method_name, None)
        if not callable(method):
            continue
        try:
Confidence
50% confidence
Finding
Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
The docstring states that the function prefers UTF-8 output so Chinese text stays readable, which signals a language-specific assumption in the tool's user-facing behavior. There is no accompanying user opt-in or broader language/locale choice explaining whether other locales are equally supported.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
tests/test_hik_open_device_control.py:17