Back to skill

Security audit

海康云眸设备告警能力管理

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but it can change live alarm monitoring and handle Hik-Cloud credentials with weak destination and token-cache safeguards.

Install only if you trust the configured Hik-Cloud endpoint and understand that the skill can change live alarm and detection settings. Prefer environment-injected credentials over command-line tokens, avoid custom base URLs unless they are controlled and HTTPS, and protect or disable the token cache where possible.

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_alarm_capability_management.py:103
Finding
Unrestricted Base URL Can Receive OAuth Credentials and Bearer Tokens## Vulnerability Details **File Location**: `scripts/hik_open_device_alarm_capability_management.py:103-114, 182-198, 245-262, 359` **Vulnerability Type**: Arbitrary credential destination and insecure transport configuration **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("/") def resolve_base_url(explicit_base_url: str | None) -> str: if explicit_base_url: return normalize_base_url(explicit_base_url) env_base_url = os.getenv(BASE_URL_ENV_VAR) if env_base_url: return normalize_base_url(env_base_url) return DEFAULT_BASE_URL ``` ```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 def api_request( base_url: str, timeout: float, cache_file: Path, explicit_token: str | None, spec: RequestSpec, force_refresh: bool = False, ) -> dict[str, Any]: if force_refresh and cache_file.exists(): cache_file.unlink() 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, ) ``` ```pyt ...[truncated 3000 chars]
Remediation
## Remediation Suggestions 1. Require `https` for all credential-bearing requests and reject plain HTTP. 2. Allowlist `api2.hik-cloud.com` as the production destination. 3. If custom environments are required, require an explicit development-mode opt-in and maintain a configurable allowlist of trusted hosts. 4. Parse the URL with `urllib.parse.urlsplit()` and reject: - Schemes other than HTTPS. - Missing or unapproved hostnames. - Embedded usernames or passwords. - Fragments. - Unexpected ports unless explicitly authorized. 5. Do not permit production client credentials or bearer tokens to be forwarded to arbitrary custom endpoints. 6. Consider using separate test credentials when a non-production endpoint is selected. 7. Add tests proving that HTTP URLs, attacker-controlled hosts, user-information URLs, and malformed authority components are rejected. 8. Clearly warn operators that command-line access tokens may be exposed through process listings; prefer environment injection or protected credential storage.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/hik_open_device_alarm_capability_management.py:127
Finding
Bearer Token Cache Is Written Without Enforced Private Permissions## Vulnerability Details **File Location**: `scripts/hik_open_device_alarm_capability_management.py:127-129` **Vulnerability Type**: Insecure plaintext credential storage **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 OAuth response, including the reusable `access_token`, is serialized as plaintext JSON. The script relies on the process umask and existing filesystem permissions rather than explicitly enforcing private access. The code does not: - Create the cache directory with an enforced owner-only mode such as `0700`. - Create the token file with an enforced mode such as `0600`. - Correct unsafe permissions on an existing cache file. - Validate file ownership or reject symbolic links. - Use atomic, exclusive file creation before replacing the cache. - Restrict the configurable `--token-cache-file` to a private location. On systems with a permissive umask, unsafe pre-existing paths, or shared cache locations, another local account or process may be able to read the bearer token. Writing through a predictable path without symlink checks may also cause the secret to be written through an attacker-prepared filesystem entry where local permissions permit that setup. ### Attack Path 1. The Skill runs with valid client credentials and no currently valid cached token. 2. The script obtains a new OAuth bearer token. 3. The process has a permissive umask, the selected cache file has unsafe existing permissions, or the user supplies a shared `--token-cache-file` location. 4. `save_token_cache()` writes the bearer token without enforcing owner-only access. 5. Another local user or process reads the token from the JSON file. 6. The attacker reuses the to ...[truncated 649 chars]
Remediation
## Remediation Suggestions 1. Create the cache directory with mode `0700` and verify that it is owned by the current user. 2. Create token files atomically with owner-only mode `0600`, for example by using `os.open()` with restrictive flags and permissions. 3. Write to a securely created temporary file in the same directory, flush and synchronize it, then atomically replace the cache file. 4. Reject symbolic links and files not owned by the current user. 5. Verify and repair permissions before reading or updating an existing cache. 6. Warn or fail when `--token-cache-file` points to a group-writable, world-writable, or shared directory. 7. Prefer an operating-system credential store or secret-management service where available. 8. Add automated tests that verify cache directory and file modes and confirm that symbolic-link targets are rejected.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
声明描述的是一个可执行的海康云眸设备报警能力管理技能,但代码实际只是测试/契约校验代码,用于验证文档内容是否声明了 skillKey、所需环境变量、隐藏 token 流程、缓存文件路径以及字段说明。其主要行为是读取本地 markdown 文件并做字符串断言,和声明中的对外 API 能力管理功能存在实质性不一致。因此应判定为描述与代码行为不匹配。

Credential Access

High
Category
Privilege Escalation
Content
通用参数:

- `--base-url`:显式指定接口域名,优先级高于环境变量
- `--access-token`:显式指定 access token
- `--timeout`:请求超时秒数,默认 `20`
- `--token-cache-file`:token 缓存文件,默认 `~/.cache/hik_open/token.json`
- `--format`:`text` 或 `json`
Confidence
91% confidence
Finding
The skill explicitly supports supplying an `--access-token` and storing tokens in a cache file, which are credential-handling behaviors. In an agent environment, bearer tokens are highly sensitive: they can be exposed through command-line history, process inspection, logs, or permissive file permissions on the cache, enabling unauthorized API access as the tenant.

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.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill documentation directs use of environment variables, token cache files, local script execution, and outbound API calls, but it does not declare any explicit tool scope or permissions. This creates an authorization and review gap: an agent may use network, file, and secret-reading capabilities without clear restriction, making accidental overreach or unsafe execution more likely.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The natural-language description is entirely in Chinese and specifies usage conditions in Chinese without indicating that users may interact in other languages or opt into a locale. Under the stated policy, forcing a specific language without user choice is a locale-policy concern unless clearly documented as region-specific and justified.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill instructs users to inject `HIK_OPEN_CLIENT_ID`, `HIK_OPEN_CLIENT_SECRET`, and optionally pass `--access-token`, but it does not include explicit safeguards against exposing secrets in logs, shell history, command traces, or structured output. Because the skill also supports cached tokens and JSON output, mishandling could leak reusable credentials or bearer tokens to users, logs, or downstream systems.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This markdown file states that the skill will automatically obtain, cache, refresh, and inject OAuth access tokens, and it lists client credentials in environment variables. For markdown files, SQP-2 applies when the skill description omits warnings about behaviors that could affect privacy or system integrity; here there is no warning that the skill handles sensitive credentials and authentication tokens automatically.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The referenced skill explicitly supports changing alarm ability status and toggling intelligent detection, which can weaken or disable device monitoring if used without clear warning, authorization checks, or user confirmation. In the context of security and surveillance devices, undocumented state-changing operations are safety-relevant because a user may not realize they are reducing protection coverage rather than performing a read-only query.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The script stores bearer token material in a predictable file under the user's home directory without setting restrictive file permissions or using an OS-backed secret store. If another local user, process, backup system, or malware can read that file, the token can be reused to access the Hik-Cloud API with the script's privileges until expiry.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
The script sends client credentials to the token endpoint and later sends authorization tokens and device-related identifiers in API requests. Although this is part of the helper's purpose, there is no user-facing disclosure in the code about network transmission of sensitive authentication material or device metadata.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
This code requires specific Chinese phrases to appear in the skill documentation, and additional assertions later require more Chinese-language text. That effectively enforces a fixed language/locale in the skill's natural-language content, with no evidence here of user choice or documented regional justification.

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.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
tests/test_hik_open_device_alarm_capability_management.py:22