Back to skill

Security audit

insentek-api-skill

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated IoT data purpose, but its credential handling has real exposure risks that users should review before installing.

Install only if you trust this publisher and are comfortable storing Insentek API credentials locally. Prefer the interactive login prompt, do not pass secrets via --secret, avoid setting INSENTEK_API_BASE unless you fully trust the endpoint, and rotate credentials if they may have been exposed in shell history, logs, or generated URLs.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/credential_store.py:20
Finding

Credential encryption relies on predictable machine metadata

Content
View full analysis
bytes: username = getpass.getuser() hostname = socket.gethostname() material = f"{hostname}:{username}{KEY_MATERIAL_SUFFIX}".encode("utf-8") return hashlib.scrypt( material, salt=SCRYPT_SALT, n=2**14, r=8, p=1, dklen=32, ) ``` The equivalent Node.js implementation is: ```javascript export const SCRYPT_SALT = 'insentek-skill-salt-v1'; const KEY_MATERIAL_SUFFIX = ':insentek-openapi-skill'; function deriveKeyMaterial() { const { username } = os.userInfo(); return `${os.hostname()}:${username}${KEY_MATERIAL_SUFFIX}`; } function deriveKey() { return crypto.scryptSync(deriveKeyMaterial(), SCRYPT_SALT, 32); } ``` ### Technical Analysis Although the stored fields use authenticated AES-256-GCM encryption, the encryption key is derived solely from: - The local username - The local hostname - A hardcoded suffix - A hardcoded scrypt salt None of these values constitutes a secret. A party that obtains `credentials.json` can reproduce the key if the username and hostname are known or guessed. These values are often exposed in backups, prompts, logs, inventory systems, device names, or other files on the same host. The use of scrypt increases the computational cost of guessing, but it does not compensate for the low entropy and predictability of the source material. File mode `0600` reduces access by other local users but does not protect copied backups, accidentally exposed archives, or files obtained through another compromised process running as the user. The hostname acce ...[truncated 1245 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/insentek_cli.py:121
Finding

App Secret is transmitted in an HTTP URL query string

Content
View full analysis
({})); ``` ### Technical Analysis The token request is constructed as: ```text GET /v3/token?appid=&secret= ``` HTTPS protects the request while in transit, but it does not prevent the complete URL from being recorded after TLS termination. Query strings are frequently retained by: - Reverse-proxy and load-balancer access logs - API gateways and web application firewalls - Application performance monitoring systems - Error telemetry and request tracing - Debugging proxies and network diagnostics - Server-side request logs Unlike a short-lived request token, the App Secret is a persistent credential. Its inclusion in the URL unnecessarily expands the number of systems that may retain it. ### Attack Path 1. A user runs the login command or the client refreshes its token. 2. The client sends a GET request containing `appid` and `secret` in the URL. 3. A proxy, gateway, server, tracing platform, or diagnostic component records the ...[truncated 583 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/insentek_cli.py:44
Finding

Unrestricted API base override can redirect credentials and bearer tokens

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
packages/insentek-skill-cli/lib/cli.js:431
Finding

Non-interactive login exposes App Secrets through command-line arguments

Content
View full analysis
', 'App ID (non-interactive)') .option('--secret ', 'App Secret (non-interactive)') .option('-y, --yes', 'Overwrite existing credentials without prompting', false) .action(async (opts, command) => { const json = getJsonFlag(command); try { const result = await runLogin({ yes: opts.yes, appid: opts.appid, secret: opts.secret, json, }); ``` The value is directly consumed as follows: ```javascript export async function runLogin({ yes = false, appid = null, secret = null, json = false, } = {}) { const resolvedAppId = appid?.trim() || await input({ message: 'Insentek App ID', validate: (value) => (value.trim() ? true : 'App ID is required'), }); const resolvedSecret = secret?.trim() || await password({ message: 'Insentek App Secret', mask: '*', validate: (value) => (value.trim() ? true : 'App Secret is required'), }); ``` ### Technical Analysis The interactive password prompt masks the App Secret, but the `--secret` option permits the same persistent credential to be supplied in the process argument vector. Depending on the platform and execution environment, command-line arguments can be exposed through: - Shell history - Process inspection utilities - CI/CD job logs - Agent tool-call records - Terminal session recording - Endpoint monitoring and command auditing - Error reports that include the executed command The issue exists even though the secret is later encrypted at rest because disclosure occurs before ...[truncated 726 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
docs/analysis.md:56
Finding

Generated HTML reports load mutable third-party JavaScript without integrity verification

Content
View full analysis
body { font-family: sans-serif; max-width: 960px; margin: 0 auto; } ``` ### Technical Analysis The recommended report template loads ECharts from a remote CDN using only the major version selector `@5`. The resource is therefore mutable and can resolve to different code after the Skill has been reviewed. The tag also omits a Subresource Integrity hash. When a user opens a generated report, the browser retrieves and executes the current CDN response. If the CDN, package publishing account, dependency release, or delivery path is compromised, attacker-controlled JavaScript can execute in the report's browser context. The remote script may be able to read report contents, including device identifiers, locations, measurements, and analysis results. It can then issue outbound network requests permitted by the browser. This does not establish automatic local code execution outside the browser sandbox, but it creates an unnecessary supply-chain execution channel. ### Attack Path 1. A report is generated using the documented template. 2. The report contains the mutable jsDelivr ECharts URL. 3. The CDN resource or upstream package content is maliciously modified or compromised. 4. A user opens the report while network access is available. 5. The browser downloads and executes the changed JavaScript. 6. The script reads report data and may transmit it to an external service or alter the report presented to the user. ### Impact Assessment Successful exploitation can compromise the confidentiality and integrity of generated report contents in the browser context. Th ...[truncated 289 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (174)

Tainted flow: 'req' from os.environ.get (line 38, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The request target is derived from API_BASE_URL, which can be overridden from the environment or CLI, and the script sends the provided Authorization token to that endpoint. This creates an SSRF-like/exfiltration risk: a malicious or misconfigured base URL can cause sensitive credentials and queried device data to be transmitted to an attacker-controlled server.

Content

Scanner excerpt · scripts/export_excel.py (reported line 43)May include surrounding context.

python
for k, v in headers.items():
            req.add_header(k, v)
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        body = e.read().decode("utf-8")

Tainted flow: 'req' from os.environ.get (line 78, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

API_BASE_URL is taken from the INSENTEK_API_BASE environment variable and used directly to build outbound requests, including authenticated requests carrying the bearer token and token-fetch requests carrying appid and secret as query parameters. If an attacker can influence the environment or CLI --api-base, they can redirect traffic to an attacker-controlled host and exfiltrate credentials or device data via SSRF-style endpoint substitution.

Content

Scanner excerpt · scripts/insentek_cli.py (reported line 87)May include surrounding context.

python
req.data = json.dumps(data).encode("utf-8")

    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        # 认证失败,尝试刷新 token 后重试一次

Tainted flow: 'req' from os.environ.get (line 78, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The environment check performs a network request to a caller-controlled api_base value without validating the destination. While this path does not include credentials by itself, it still enables arbitrary outbound requests from the running environment, which can be abused for SSRF, internal network probing, or misleading health-check results.

Content

Scanner excerpt · scripts/insentek_cli.py (reported line 571)May include surrounding context.

python
# 7. API 可达性(不带认证,只检查服务是否在线)
    try:
        req = urllib.request.Request(f"{api_base}/v3/token", method="GET")
        with urllib.request.urlopen(req, timeout=10) as resp:
            # 400 是正常的(缺少参数),说明服务在线
            results["api_reachable"] = {
                "ok": True,

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · CHANGELOG.md (reported line 28)May include surrounding context.

md
Added
-----

- **`latest` 子命令**:`scripts/insentek_cli.py` 新增 `latest --sn SN`,统一走加密凭据 + 自动刷新 token,取代 SKILL.md 之前不可执行的 `curl /v3/device/{sn}/latest` 示例(Agent 无法从加密凭据中拿到明文 token)
- **统一错误信封 `normalize_error`**:`cmd_data` / `get_latest` 现在把内部 `_validation_error` / `_http_error` / `authentication_required` 统一转换为 `{success: false, error: <kind>, message: ...}`,并对上游 WAF HTML 错误页截断到 500 字符

Fixed

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · CHANGELOG.md (reported line 28)May include surrounding context.

md
Added
-----

- **`latest` 子命令**:`scripts/insentek_cli.py` 新增 `latest --sn SN`,统一走加密凭据 + 自动刷新 token,取代 SKILL.md 之前不可执行的 `curl /v3/device/{sn}/latest` 示例(Agent 无法从加密凭据中拿到明文 token)
- **统一错误信封 `normalize_error`**:`cmd_data` / `get_latest` 现在把内部 `_validation_error` / `_http_error` / `authentication_required` 统一转换为 `{success: false, error: <kind>, message: ...}`,并对上游 WAF HTML 错误页截断到 500 字符

Fixed

Hidden Instructions

High
Category
Prompt Injection
Confidence
60% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · CLAUDE.md (reported line 1)May include surrounding context.

md
# insentek-api-skills

This is a GSD-managed project. Use `/gsd-progress` to check status and next steps.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description says the skill lets users query Insentek IoT device data via natural language. However, this code chunk does not implement device-data querying, trend analysis, comparison, or export. Instead, it implements a CLI bootstrap and lifecycle manager for the skill itself: install/update/uninstall/status/info/doctor commands plus login/logout/auth status for API credentials. While credential management may support the overall product, the primary behavior of this code chunk is operational tooling, not IoT data access. That is a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description says the skill lets users query Insentek IoT device data via natural language and analyze/export that data. The supplied code does not implement any data querying, analytics, comparison, or export behavior. Instead, it is a maintenance/diagnostic command for the skill CLI that verifies packaged assets, local installation health, runtime support, Python availability, and API credential presence. These are materially different capabilities and represent a different primary purpose from the declared user-facing functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description centers on querying and analyzing Insentek IoT device data via natural language. However, this code chunk is exclusively an authentication/credential-management command for a CLI. While login can be a supporting function for the broader skill, the chunk itself does not implement the described user-facing data access capabilities and instead performs a distinct capability—credential collection, login, and token handling, including printing the secret/token. Therefore the code chunk's behavior does not accurately match the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description focuses on querying and analyzing IoT device data via natural language. However, the supplied code does not query device data, analyze trends, compare devices, or export data. Instead, it performs account/session-related functionality by removing saved credentials from a credentials file and reporting status. This is a materially different primary purpose and an undeclared capability unrelated to the described data-querying behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose is an IoT data query/analysis capability for Insentek devices, but the supplied code does not access device APIs, telemetry, historical data, analytics, comparison, or export functionality. Instead, it performs package/runtime management tasks on the local filesystem: resolving install locations, checking whether a skill is installed, reading manifests, and deleting installation directories. This is a materially different primary purpose and involves undeclared capabilities unrelated to the described Insentek data-query behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose is an end-user data access skill for querying Insentek IoT device data. The supplied code chunk does not query devices, fetch real-time or historical telemetry, analyze trends, compare devices, or export queried data. Instead, it is deployment/packaging infrastructure that copies skill assets on the local filesystem and can overwrite existing directories atomically with cleanup and rollback logic. This is a materially different purpose from the description, so it should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description promises an end-user data-query skill for Insentek IoT devices, including real-time and historical data access, trend analysis, comparison, and export. The actual code chunk is purely package-management/installer infrastructure for a skill CLI. Its primary purpose is deployment/update of the skill itself, not accessing device data. This is a material description-behavior mismatch, not merely a supporting detail, because the code shown exposes capabilities unrelated to the declared user-facing function and lacks any evidence of the declared data-query behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述聚焦于 insentek 物联网设备数据查询与分析能力,但提供的代码片段仅进行本地路径和工作区标记检测(如 .openclaw、openclaw.json、.claude、.git、skills),属于技能/CLI 安装与解析基础设施代码。它没有展示任何与设备通信、数据读取、历史查询、趋势分析、跨设备对比或数据导出相关的实现。因此该代码片段的实际行为与声明的主要用途明显不一致,应判定为描述与行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose concerns querying and analyzing Insentek IoT device data via natural language. However, the supplied code does not interact with IoT devices, data sources, APIs, analytics, comparisons, or exports. Instead, it is a utility module for managing runtime scopes in a CLI/tooling context. This is a materially different primary purpose, so the description does not accurately represent the code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose is focused on querying and analyzing Insentek IoT device data via natural language. The actual code chunk does not implement any device communication, data retrieval, analysis, comparison, or export functionality. Instead, it performs local environment and path-handling tasks using the Node.js os module, including reading the user's home directory. While such utilities could be supportive in a larger CLI application, this chunk by itself is unrelated to the declared device-data functionality and accesses local system information not mentioned in the description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述的是一个面向 insentek 物联网设备的数据查询与分析技能;而提供的代码片段仅实现 CLI 辅助功能,涉及本地文件系统检查、环境探测、运行时/安装位置信息整理和 JSON 输出。它没有任何与设备通信、自然语言查询解析、实时或历史数据获取、趋势分析、跨设备对比、数据导出相关的实现。虽然这可能是该项目中的配套 CLI 模块,但就该代码片段本身而言,其行为与声明用途明显不符,因此应判定为描述与实际行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about querying and analyzing insentek IoT device data via natural language. The supplied code does not interact with IoT devices, data sources, analytics, historical records, exports, or user queries. Instead, it performs local runtime configuration logic for locating Claude Code skills directories. This is a materially different primary purpose and represents unrelated capabilities, so the description does not accurately match the code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about querying and analyzing Insentek IoT device data via natural language. However, the supplied code chunk does not perform any device communication, data querying, analytics, comparison, or export. Instead, it is infrastructure code for choosing supported runtimes and locating installed skill directories on the filesystem. This is a materially different primary purpose from the declared functionality, so it should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description says this skill queries Insentek IoT device data and performs analytics/export functions. However, the supplied code does none of that. It only resolves local filesystem locations for an OpenClaw skills directory depending on runtime scope. This is a materially different primary purpose and involves local path handling rather than device data access, querying, analytics, or export. Therefore the description does not accurately represent the code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose is an IoT data query skill for Insentek devices, but this code chunk does not show any device-data access, querying, analytics, comparison, or export logic. Instead, it provides generic CLI helper functions that interact with the local filesystem and can execute arbitrary external commands. While utility code can support a larger application, the capabilities present here materially involve undeclared local resource access and command execution, which are not represented in the description or permissions. Therefore this chunk does not accurately match the declared behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

声明描述的是一个面向用户的物联网设备数据查询与分析技能;但提供的代码片段并未实现任何自然语言处理、设备通信、数据查询、趋势分析、跨设备比较或数据导出功能。相反,它只是在本地文件系统中复制文档和配置文件、清理目标目录并同步版本号,属于构建/打包流程的资产同步脚本。其主要目的与声明用途明显不一致,因此应判定为描述与实际行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

代码片段并未体现任何与 insentek 物联网设备数据查询、实时/历史数据读取、趋势分析、跨设备对比或数据导出相关的行为。相反,它是针对一个命令行工具的自动化测试,重点检查运行时信息、安装状态、doctor 检查以及 JSON 输出结构。这与声明的核心用途 materially different,属于明显不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

代码片段的核心功能是本地文件系统层面的单元测试:创建临时目录、写入测试夹具、调用 replaceDirectoryAtomic、验证版本替换、失败时保留原安装、以及清理临时目录。这与声明的“自然语言查询 insentek 物联网设备数据”没有直接关系,也没有体现设备数据访问、实时/历史查询、趋势分析、跨设备对比或数据导出能力。该代码既未展示任何 IoT API 调用,也未处理用户查询,因此其实际行为与声明用途存在明显且实质性的不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

声明描述的核心能力是面向 insentek 设备数据的自然语言查询与分析,但提供的代码片段并未实现任何设备数据获取、查询、分析、对比或导出逻辑。相反,这段代码是针对 credentials 模块的测试,主要验证凭据加密存储、加载、删除以及脱敏显示。这属于与声明目的明显不同的能力与资源访问(本地文件系统/环境变量),因此构成实质性不匹配。

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.potential_exfiltration

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
packages/insentek-skill-cli/lib/python.js:9

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
packages/insentek-skill-cli/lib/utils.js:34

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
packages/insentek-skill-cli/test/cli-json.test.js:11

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
packages/insentek-skill-cli/lib/core/credentials.js:119