- 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.