Back to skill

Security audit

海康云眸设备分组管理

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but it handles cloud admin credentials and destructive device-group changes without enough safeguards.

Review before installing. Use only trusted HTTPS Hik-Cloud endpoints, avoid passing bearer tokens with --access-token, store credentials in a controlled environment, restrict the token cache path and permissions, and require an explicit human check before delete or device-transfer operations.

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_group_management.py:97
Finding

Credentials and bearer tokens can be redirected to arbitrary or plaintext endpoints

Content
View full analysis
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", }, ) 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}" ) ``` ```python token_payload = fetch_access_token(base_url, client_id, client_secret, timeout) ``` ### Technical Analysis The Skill legitimately needs to transmit a client ID and client secret to the Hik-Cloud token endpoint. However, the destination is derived from the `--base-url` argument or `HIK_OPEN_BASE_URL` environment variable without validating the URL scheme, hostname, port, user information, or intended trust boundary. Consequently, the script permits ...[truncated 2364 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/hik_open_device_group_management.py:122
Finding

Access tokens are cached without explicitly restrictive filesystem permissions

Content
View full analysis
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 function writes a bearer access token to a plaintext JSON file but does not explicitly enforce owner-only permissions on either the cache directory or token file. The resulting permissions depend on the process umask and the state of any pre-existing file. Under a permissive umask, the token file may be readable by other local users. If the caller selects a shared path through `--token-cache-file`, the exposure may be broader. An existing file can also retain unsafe permissions because the function does not validate or correct its mode. The write is not performed using an exclusive or symlink-resistant file operation. In environments where another local actor can manipulate the selected cache path or its parent directory, that actor may be able to influence where the token is written. ### Attack Path 1. The Skill runs with a permissive umask, an unsafe pre-existing cache file, or a cache path inside a shared directory. 2. The script obtains a fresh bearer token using the configured client credentials. 3. `save_token_cache` writes the token to the selected JSON file without setting mode `0600`. 4. Another local user or process reads the cache file. 5. The attacker extracts the `access_token` value and reuses it against the Hik-Cloud API before expiration. Where an attacker can modify the cache path or parent directory, symlink manipulation may also redirect the write to another attacker-readable location. ### Impact Assessment A local attacker who reads the cache obt ...[truncated 492 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

代码片段的主功能是单元测试/契约测试,只读取 SKILL.md 并断言其中包含若干固定字符串。这与声明的“设备分组管理技能”核心用途明显不符。代码没有网络请求、没有海康 API 调用、没有 token 获取/刷新逻辑、也没有任何组织或设备分组操作实现。因此这是明显的描述与行为不一致。

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
88% confidence
Finding

The skill explicitly supports passing an access token via command-line argument and also references token caching. Command-line tokens may be exposed through process listings, logs, shell history, or agent telemetry, making credential theft more likely in shared or instrumented environments.

Content

Scanner excerpt · SKILL.md (reported line 142)May include surrounding context.

md
通用参数:

- `--base-url`:显式指定接口域名,优先级高于环境变量
- `--access-token`:显式指定 access token
- `--timeout`:请求超时秒数,默认 `20`
- `--token-cache-file`:token 缓存文件,默认 `~/.cache/hik_open/token.json`
- `--format`:`text` 或 `json`

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/auth.md (reported line 7)May include surrounding context.

md
- 认证模式:`client_credentials`
- 请求参数:`client_id`、`client_secret`、`grant_type=client_credentials`、`scope=app`
- 业务接口请求头:`Authorization: Bearer <access_token>`
- access token 失效后,业务接口通常返回 HTTP `401`
- 本技能脚本会优先复用显式 token、环境变量或缓存中的 token;如果都没有,则自动使用 `HIK_OPEN_CLIENT_ID` 和 `HIK_OPEN_CLIENT_SECRET` 重新获取
- 缓存 token 若接近过期,会自动重新拉取

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/hik_open_device_group_management.py (reported line 207)May include surrounding context.

python
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))

Credential Access

High
Category
Privilege Escalation
Confidence
89% confidence
Finding

Accepting an access token via the --access-token command-line argument can expose the bearer token to other local users through process listings, shell history, job control logs, or audit tooling. In this skill context, the token grants administrative API access for device-group operations, so inadvertent disclosure could enable unauthorized modification or enumeration of Hik-Cloud resources.

Content

Scanner excerpt · scripts/hik_open_device_group_management.py (reported line 353)May include surrounding context.

python
def add_common_args(parser: argparse.ArgumentParser) -> None:
    parser.add_argument("--base-url", help="Override API base URL")
    parser.add_argument("--access-token", help="Use explicit access token")
    parser.add_argument(
        "--timeout",
        type=float,

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill documentation indicates capabilities requiring environment access, file read/write, and network access, but it does not declare any explicit tool scope such as permissions or allowed-tools. In an agent environment, undeclared capability use weakens least-privilege controls and can allow the skill to access secrets, persist data, or make outbound requests without clear review boundaries.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The trigger description uses broad natural-language scenarios such as mentions of device organization, grouping, groupNo/groupId/parentNo, and device transfer. Overly broad activation criteria can cause the skill to run in unintended contexts, increasing the chance of unnecessary credential use, unintended API calls, or accidental modification of device organization state.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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.

Content

Scanner excerpt · SKILL.md (reported line 80)May include surrounding context.

新增组:

bash
python3 {baseDir}/scripts/hik_open_device_group_management.py create \
  --group-name "华东一区" \
  --group-no "east-001" \
  --parent-no "root-01"

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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.

Content

Scanner excerpt · SKILL.md (reported line 80)May include surrounding context.

新增组:

bash
python3 {baseDir}/scripts/hik_open_device_group_management.py create \
  --group-name "华东一区" \
  --group-no "east-001" \
  --parent-no "root-01"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation states that the skill will automatically reuse explicit tokens, environment variables, or cached credentials and, if absent, obtain a new token using environment-stored client credentials, but it does not clearly warn users that invoking the skill may cause authentication with ambient credentials. In an agent context, this can lead to unintended use of privileged secrets or silent access to external systems without the user's informed consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script exposes a delete command for device groups, which is a destructive operation, but there is no confirmation prompt, cautionary log message, or warning text near the command definition or execution path. Users can invoke deletion directly and the command proceeds to call the remote API without any disclosure of irreversibility or impact.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The device-transfer subcommand performs a remote state-changing action by moving a device to another group, but the script provides no confirmation prompt or cautionary disclosure before sending the request. Although transfer is part of the tool's purpose, there is no user-facing warning that the action will immediately modify device assignment in the remote system.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The manifest presents the skill name and description in Chinese, but the default prompt is fixed in English. This can amount to a language-policy issue because the skill appears to assume a specific output/invocation language without documenting user opt-in or offering a locale choice.

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 · scripts/hik_open_device_group_management.py (reported line 82)May include surrounding context.

python
return

    for method_name in ("SetConsoleOutputCP", "SetConsoleCP"):
        method = getattr(kernel32, method_name, None)
        if not callable(method):
            continue
        try: