Back to skill

Security audit

grafana-inspector

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly performs Grafana API inspection, but one bundled script disables TLS certificate checks while using Grafana credentials and the documentation overstates screenshot/reporting features.

Review before installing. Use a read-only, narrowly scoped Grafana token, avoid username/password credentials when possible, do not run against sensitive production Grafana instances unless reports are stored in a protected location, and fix or avoid scripts/inspection_report.py until TLS verification is enabled. Expect API-based reports, not actual browser screenshots or Feishu document generation.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/inspection_report.py:66
Finding
TLS Certificate Verification Disabled for Authenticated Grafana Requests## Vulnerability Details **File Location**: `scripts/inspection_report.py:66-73` and `scripts/inspection_report.py:113-120` **Vulnerability Type**: Improper Certificate Validation (CWE-295) **Risk Level**: High ### Vulnerable Code Dashboard discovery: ```python response = requests.get( search_url, headers=self.get_auth_headers(), params=params, auth=(self.username, self.password) if self.username and self.password else None, timeout=30, verify=False ) ``` Dashboard detail retrieval: ```python response = requests.get( url, headers=self.get_auth_headers(), auth=(self.username, self.password) if self.username and self.password else None, timeout=30, verify=False ) ``` ### Technical Analysis The `verify=False` argument disables TLS certificate and hostname verification for the two Grafana API request paths. Both requests can contain sensitive authentication material: - A bearer API key added by `get_auth_headers()`. - A username and password supplied through HTTP Basic Authentication. Although HTTPS may still encrypt the connection, disabling certificate verification prevents the client from confirming that it is communicating with the intended Grafana server. A network-positioned attacker can present an arbitrary certificate, impersonate Grafana, and terminate the TLS connection without rejection by the client. This flaw affects dashboard discovery and dashboard-detail retrieval. Responses from an impersonated endpoint are also trusted as inspection input, allowing an attacker to manipulate generated reports in addition to capturing credentials. ### Attack Path 1. A user configures the Skill with an HTTPS Grafana URL and a bearer API key or username/password credentials. 2. An attacker gains a network interception position or influences DNS, routing, proxy settings, or the configured Grafana endpoint. 3. The attacker presents a certificate that is self-signed, issued for another hostname, or otherwise untrust ...[truncated 1106 chars]
Remediation
## Remediation Suggestions 1. Remove `verify=False` from both `requests.get()` calls so that Requests performs certificate and hostname validation using the operating system's trusted CA store: ```python response = requests.get( search_url, headers=self.get_auth_headers(), params=params, auth=(self.username, self.password) if self.username and self.password else None, timeout=30 ) ``` 2. For Grafana deployments using a private certificate authority, support an explicit CA-bundle configuration rather than disabling verification: ```python ca_bundle = self.config.get("ca_bundle", True) response = requests.get( search_url, headers=self.get_auth_headers(), params=params, auth=(self.username, self.password) if self.username and self.password else None, timeout=30, verify=ca_bundle ) ``` 3. Apply the same verified TLS policy consistently to dashboard discovery, dashboard-detail retrieval, and every future authenticated HTTP request. 4. Validate configuration at startup. Reject insecure or invalid CA-bundle paths and warn when credentials are used with a plaintext `http://` Grafana URL. 5. Prefer narrowly scoped, read-only Grafana service-account tokens over reusable usernames and passwords. Rotate any credentials that may previously have traversed an unverified connection. 6. Add automated tests confirming that self-signed, expired, and hostname-mismatched certificates are rejected unless an explicitly configured trusted CA validates them.
Vulnerability Patterns
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The primary purpose broadly matches Grafana inspection, including automatic dashboard discovery and multi-dashboard inspection. However, the description explicitly claims 'browser screenshots + API data inspection', while this code chunk contains no browser automation, screenshot capture, or rendering logic. It exclusively uses HTTP requests to Grafana APIs and generates reports from API responses. There are no unrelated dangerous capabilities or inconsistent resource accesses beyond Grafana API usage and local report file output. Therefore this is a description-behavior mismatch due to overstating a significant capability.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
整体上,这段代码的核心仍属于 Grafana 自动化巡检,且确实实现了自动发现仪表盘、批量分析和基于 API 的巡检,因此并非完全偏离声明目的。但声明中的重要能力“浏览器截图 + API 数据巡检”存在明显不符:代码只调用 Grafana HTTP API,没有 Selenium/Playwright/浏览器渲染或截图保存逻辑,也没有 24 小时与 7 天截图对比功能。相反,代码的实际输出是本地 JSON/Markdown 报告。由于截图能力是声明中的关键卖点之一,而代码未实现,属于实质性描述不准确,应判定为 mismatch。

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
代码的核心行为与“Grafana 自动化巡检”总体一致,尤其吻合 API 数据巡检、多仪表盘巡检(通过 dashboard_uids)以及自动发现仪表盘(auto_discover, discover_limit)这几项描述。但声明中特别提到“支持浏览器截图”,而该代码片段中没有任何浏览器驱动、页面访问、截图保存或相关调用的迹象。相反,代码仅调用 GrafanaAPIInspector 做 API 检查并输出 JSON/Markdown 报告。因此存在部分描述与实际行为不符,属于能力声明超出代码实际体现范围的 mismatch。

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The file forces a specific language/locale in its user-facing natural-language content, which can violate language-choice policy when no opt-in or alternative is provided. There is no indication that the skill is region-specific or that users can choose another language.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill declares network, file read, and file write behavior in practice but does not declare any explicit tool scope or permission boundaries in SKILL.md. In an agent environment, missing scope metadata can cause the skill to be invoked with broader capabilities than users expect, increasing the risk of unintended data access, outbound requests, and local artifact creation.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill description does not warn users that it will access Grafana data over the network and store inspection outputs, potentially including sensitive dashboard metadata, to local files. In a monitoring context, dashboards and generated reports may contain operational details, internal URLs, names, or other sensitive information, so lack of disclosure increases the risk of unintentional data exposure.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The OpenClaw invocation phrase `执行 Grafana 巡检` is broad and lacks gating conditions, target constraints, or confirmation requirements. In agent systems, overly generic triggers can cause accidental or context-inappropriate execution, potentially leading to unsolicited network access to Grafana and local report generation using stored credentials.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
Natural-language strings in the module description and command-line output are consistently fixed to Chinese, with no option for the user to select another language. This matches the language/locale policy violation category because the skill imposes a locale choice rather than offering opt-in or documenting a justified regional constraint.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script writes Markdown and JSON reports to local disk automatically, and those reports include potentially sensitive operational metadata such as Grafana URL, dashboard identifiers, alerts, and datasource inventory. In an agent/automation context, silent file creation can leak sensitive environment information into shared workspaces, logs, artifacts, or later processing stages without explicit user consent.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
模块顶部说明将该脚本描述为包含浏览器截图巡检和飞书文档报告生成,但实现中没有任何截图、浏览器自动化、时间范围对比或飞书 API 调用。实际行为是发现仪表盘、读取详情、做简单配置检查,并将报告写入本地文件。

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The module docstring and all user-facing status/report strings are written exclusively in Chinese, including the generated report content and runtime messages. This imposes a specific language on users without any opt-in, selection mechanism, or justification that the skill is restricted to a Chinese-speaking or region-specific environment.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
params=params,
                auth=(self.username, self.password) if self.username and self.password else None,
                timeout=30,
                verify=False
            )

            if response.status_code == 200:
Confidence
99% confidence
Finding
Disabling TLS certificate verification allows man-in-the-middle interception and tampering of HTTPS traffic to Grafana. In this script, that can expose API keys or basic-auth credentials and permit falsified dashboard metadata to be returned, undermining both confidentiality and report integrity.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
headers=self.get_auth_headers(),
                auth=(self.username, self.password) if self.username and self.password else None,
                timeout=30,
                verify=False
            )

            if response.status_code == 200:
Confidence
99% confidence
Finding
The second API call also disables TLS verification, creating the same man-in-the-middle risk for dashboard detail retrieval. Because this skill processes monitoring data and may use bearer tokens or passwords, the context increases severity: compromised transport can leak secrets and poison generated inspection reports across multiple dashboards.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
This Python file contains natural-language strings and docstrings entirely in Chinese, including the main banner and operational messages. Under the policy rule for language/locale, forcing a specific language without user opt-in or a documented justification is a policy concern.

Intent-Code Divergence

Low
Confidence
81% confidence
Finding
run() 的文档字符串和模块说明结合起来暗示其完成完整巡检流程,但该流程实际仅包含生成巡检数据、生成 Markdown、保存本地文件。这里的“完整”与文件头部功能声明存在直接意图偏差。

Static analysis

Detected: suspicious.insecure_tls_verification, suspicious.install_untrusted_source

HTTPS certificate verification is disabled.

Warn
Code
suspicious.insecure_tls_verification
Location
scripts/inspection_report.py:71

Install source points to URL shortener or raw IP.

Warn
Code
suspicious.install_untrusted_source
Location
scripts/config.json:2