Back to skill

Security audit

Euskalmet

Security checks for vulnerabilities and agentic risk

Overview

This weather skill is mostly coherent, but it needs Review because a diagnostic script prints part of the API private key and the dependency set is stale or not fully locked.

Before installing, treat this as a Review item: update or lock dependencies, do not run scripts/test_env.py where output is logged, and rotate the Euskalmet private key if that script has already exposed a prefix in shared logs. The main weather retrieval behavior appears purpose-aligned and not malicious.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/test_env.py:5
Finding

Private-Key Material Disclosed to Standard Output

Content
View full analysis

Vulnerability Details

File Location: scripts/test_env.py, lines 5-7
Vulnerability Type: Sensitive credential exposure through diagnostic output
Risk Level: Medium

Vulnerable Code:

python
pk = os.environ.get("EUSKALMET_API_PRIVATE_KEY")
if pk:
    print(f"FOUND: Starts with {pk[:30]}...")
    print(f"Line count: {len(pk.splitlines())}")

Technical Analysis

The credential-testing script reads EUSKALMET_API_PRIVATE_KEY from the environment and prints its first 30 characters. Private-key material must never be emitted to standard output, even partially. Terminal output may be retained in shell logs, CI/CD logs, agent execution transcripts, monitoring systems, or support diagnostics.

The script does not transmit the private key over the network, and the reviewed code contains no evidence of intentional credential exfiltration. Nevertheless, exposing a recognizable private-key prefix violates secret-handling best practices and creates an unnecessary disclosure path. Printing the key's line count also reveals structural metadata that is not required to establish whether the credential exists.

Attack Path

  1. A user stores the Euskalmet private key in .env as documented.
  2. The user runs scripts/test_env.py to validate the environment.
  3. The script loads the private key into memory.
  4. The first 30 characters and line-count metadata are written to standard output.
  5. An execution environment, agent transcript, CI system, terminal recorder, or log collector retains that output.
  6. An attacker with access to those logs obtains a fragment and structural information about the private key.
  7. The fragment may be correlated with other disclosures or used to identify the key format and affected credential.

Impact Assessment

This issue does not independently disclose the complete private key or directly grant API access. Its immediate scope is partial exposure of an authenticatio ...[truncated 381 chars]

Remediation
View remediation

Remediation Suggestions

  • Never print any portion, hash, length, line count, or format details of a private key.

  • Replace the diagnostic output with a boolean presence check:

    python
    pk = os.environ.get("EUSKALMET_API_PRIVATE_KEY")
    if pk:
        print("EUSKALMET_API_PRIVATE_KEY is configured.")
    else:
        print("EUSKALMET_API_PRIVATE_KEY is not configured.")
    
  • If credential validity must be tested, sign a short-lived JWT and make a minimal authenticated request to the expected official API endpoint without logging the token or key.

  • Configure CI and agent environments to redact credential-related environment variables from logs.

  • Rotate the private key if the existing script has been executed in an environment whose output was retained or shared.

T08 · Insecure Dependencies

Note
Location
requirements.txt:10
Finding

Unpinned Third-Party Dependency Produces Non-Reproducible Installations

Content
View full analysis

Vulnerability Details

File Location: requirements.txt, line 10
Vulnerability Type: Unpinned dependency and insufficient package integrity controls
Risk Level: Low

Vulnerable Code:

text
certifi==2022.12.7
cffi==1.15.1
charset-normalizer==3.1.0
cryptography==40.0.1
idna==3.4
pycparser==2.21
PyJWT==2.6.0
requests==2.28.2
urllib3==1.26.15
python-dotenv

The documented installation command in SKILL.md executes this dependency specification directly:

bash
./venv/bin/pip install -r requirements.txt

Technical Analysis

python-dotenv is declared without an exact version. Consequently, installation behavior depends on whichever release the configured package index resolves at installation time. This makes the environment non-reproducible and allows dependency code to change after the Skill has been reviewed.

The remaining dependencies are version-pinned, but the requirements file does not include cryptographic hashes. Version pinning alone therefore does not verify artifact integrity. There is no evidence that python-dotenv is malicious, misspelled, or sourced from an unauthorized repository; this finding concerns avoidable supply-chain exposure rather than a confirmed compromised package.

Attack Path

  1. A user follows the setup instructions and runs pip install -r requirements.txt.
  2. pip contacts the configured package index and resolves the current compatible release of the unpinned python-dotenv package.
  3. A future compromised, malicious, or unexpectedly incompatible release is selected without any change to this repository.
  4. The package is installed into the Skill's environment.
  5. Package installation behavior or imported runtime code executes with the permissions of the user running the Skill.
  6. Malicious dependency code could access files, environment variables, and network resources available to that user, including the documented Euskalme ...[truncated 859 chars]
Remediation
View remediation

Remediation Suggestions

  • Pin python-dotenv to a specifically reviewed version, for example:

    text
    python-dotenv==<reviewed-version>
    
  • Generate and commit a locked requirements file containing cryptographic hashes, such as with:

    bash
    pip-compile --generate-hashes requirements.in
    
  • Enforce artifact verification during installation:

    bash
    pip install --require-hashes -r requirements.txt
    
  • Review and update all pinned dependencies regularly rather than allowing implicit upgrades.

  • Use only trusted package indexes and explicitly configure the expected index URL in controlled deployment environments.

  • Install dependencies in the documented isolated virtual environment under an unprivileged user account.

  • Add automated dependency vulnerability and provenance scanning to the release process.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (37)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill includes setup-validation and filesystem inspection scripts that go beyond direct weather retrieval, such as checking local files, virtualenv layout, and dependency imports. While often legitimate for development, bundling them into the skill without clear scoping broadens local access and can normalize unnecessary host inspection.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The skill includes setup-validation and filesystem inspection scripts that go beyond direct weather retrieval, such as checking local files, virtualenv layout, and dependency imports. While often legitimate for development, bundling them into the skill without clear scoping broadens local access and can normalize unnecessary host inspection.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill includes setup-validation and filesystem inspection scripts that go beyond direct weather retrieval, such as checking local files, virtualenv layout, and dependency imports. While often legitimate for development, bundling them into the skill without clear scoping broadens local access and can normalize unnecessary host inspection.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill includes setup-validation and filesystem inspection scripts that go beyond direct weather retrieval, such as checking local files, virtualenv layout, and dependency imports. While often legitimate for development, bundling them into the skill without clear scoping broadens local access and can normalize unnecessary host inspection.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: certifi==2022.12.7 — 4 advisory(ies): CVE-2024-39689 (Certifi removes GLOBALTRUST root certificate); CVE-2023-37920 (Removal of e-Tugra root certificate); CVE-2023-37920 (Certifi 2023.07.22 removes root certificates from "e-Tugra" from the root store.) +1 more

High
Category
Supply Chain
Confidence
93% confidence
Finding

certifi==2022.12.7 is outdated and associated with trust-store changes and published advisories. In a weather skill that likely makes HTTPS requests, stale CA bundles can lead to improper certificate trust decisions or connectivity/security issues when validating remote servers.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: cryptography==40.0.1 — 16 advisory(ies): CVE-2023-50782 (Python Cryptography package vulnerable to Bleichenbacher timing oracle attack); GHSA-537c-gmf6-5ccf (Vulnerable OpenSSL included in cryptography wheels); GHSA-5cpq-8wj7-hf2v (Vulnerable OpenSSL included in cryptography wheels) +13 more

High
Category
Supply Chain
Confidence
97% confidence
Finding

cryptography==40.0.1 has multiple published advisories, including issues affecting cryptographic operations and bundled OpenSSL components. Even if this skill is mainly a weather client, any use of TLS, token handling, or certificate validation depends on this library chain, making outdated cryptography components a meaningful risk.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: idna==3.4 — 4 advisory(ies): CVE-2026-45409 (Internationalized Domain Names in Applications (IDNA): Specially crafted inputs ); CVE-2024-3651 (Internationalized Domain Names in Applications (IDNA) vulnerable to denial of se); CVE-2024-3651 (A vulnerability was identified in the kjd/idna library, specifically within the ) +1 more

High
Category
Supply Chain
Confidence
82% confidence
Finding

idna==3.4 is flagged with advisories related to maliciously crafted internationalized domain inputs. This matters less in a narrowly scoped weather skill than in a general browser-like client, but if any user-influenced URLs, redirects, or hostnames are processed, it could contribute to denial of service or domain-confusion issues.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: PyJWT==2.6.0 — 9 advisory(ies): CVE-2026-32597 (PyJWT accepts unknown `crit` header extensions); CVE-2026-48522 (PyJWKClient: missing scheme allowlist enables CVE-2024-21643-class SSRF + token ); CVE-2026-48524 (PyJWKClient unbounded JWKS endpoint requests via attacker-controlled kid values ) +6 more

High
Category
Supply Chain
Confidence
80% confidence
Finding

PyJWT==2.6.0 has multiple advisories, but the actual exploitability depends on whether this skill parses, validates, or fetches JWT/JWKS data. In the provided skill context, a weather integration does not obviously require JWT handling, so this may be dormant risk from an unnecessary or indirectly used dependency rather than an immediately reachable flaw.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: requests==2.28.2 — 8 advisory(ies): CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi); CVE-2026-25645 (Requests has Insecure Temp File Reuse in its extract_zipped_paths() utility func) +5 more

High
Category
Supply Chain
Confidence
96% confidence
Finding

requests==2.28.2 has several published advisories affecting redirect handling, credential leakage, and request verification behavior. Because a weather skill is likely making outbound HTTP(S) requests to external APIs, vulnerabilities in the primary HTTP client are directly relevant and can expose secrets, mishandle TLS/proxy behavior, or weaken request safety.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: urllib3==1.26.15 — 16 advisory(ies): CVE-2025-66471 (urllib3 streaming API improperly handles highly compressed data); CVE-2024-37891 (urllib3's Proxy-Authorization request header isn't stripped during cross-origin ); CVE-2026-21441 (Decompression-bomb safeguards bypassed when following HTTP redirects (streaming ) +13 more

High
Category
Supply Chain
Confidence
97% confidence
Finding

urllib3==1.26.15 is affected by numerous advisories, including issues relevant to redirects, proxy headers, and response handling. Since urllib3 underpins common Python HTTP behavior and this skill likely consumes remote weather endpoints, vulnerabilities here are directly in the request path and can materially increase network-layer risk.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

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

md
from datetime import datetime
from dotenv import load_dotenv

# Load .env file
load_dotenv()

# Parse command-line arguments

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/format_forecast.py (reported line 7)May include surrounding context.

python
from datetime import datetime
from dotenv import load_dotenv

# Load .env file
load_dotenv()

# Parse command-line arguments

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/test_structure.py (reported line 23)May include surrounding context.

python
# Check main files
    checks.append(check_file("scripts/main.py", "Main script"))
    checks.append(check_file("requirements.txt", "Requirements file"))
    checks.append(check_file(".env", "Environment file"))
    checks.append(check_file("available-locations.json", "Locations file"))
    checks.append(check_file("SKILL.md", "Skill documentation"))

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
82% confidence
Finding

The skill documents executable scripts with network, filesystem, and environment-variable access but does not declare any explicit tool scope or permissions boundaries. This increases the chance that an agent executes broader capabilities than users expect, especially because the skill also references local file writes and credential-backed API calls.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation states that format_forecast.py formats output into a human-readable message in Basque, and the rest of the examples and file descriptions reinforce Basque-only output. Under the policy rules, forcing a specific language without user choice is a natural-language policy violation unless it is explicitly justified as a region-specific constraint or made optional.

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 97)May include surrounding context.

1. Virtual Environment

Create (or recreate) the virtual environment with Python 3.12:

bash
cd ~/.openclaw/skills/euskalmet

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · forecasts/gasteiz-euskalmet.json (reported line 1)May include surrounding context.

json
import requests

OLD_BASE_URL = (
    "https://api.euskadi.eus/appcont/meteorologia/meteodat/images/{number:02}.png"
)
MODERN_BASE_URL = "https://www.euskalmet.euskadi.eus/media/assets/icons/euskalmet/webmet00-i{number:02}d.svg"

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · forecasts/laudio-euskalmet.json (reported line 1)May include surrounding context.

json
import requests

OLD_BASE_URL = (
    "https://api.euskadi.eus/appcont/meteorologia/meteodat/images/{number:02}.png"
)
MODERN_BASE_URL = "https://www.euskalmet.euskadi.eus/media/assets/icons/euskalmet/webmet00-i{number:02}d.svg"

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/download_images.py (reported line 6)May include surrounding context.

python
import requests

OLD_BASE_URL = (
    "https://api.euskadi.eus/appcont/meteorologia/meteodat/images/{number:02}.png"
)
MODERN_BASE_URL = "https://www.euskalmet.euskadi.eus/media/assets/icons/euskalmet/webmet00-i{number:02}d.svg"

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/main.py (reported line 14)May include surrounding context.

python
import requests

OLD_BASE_URL = (
    "https://api.euskadi.eus/appcont/meteorologia/meteodat/images/{number:02}.png"
)
MODERN_BASE_URL = "https://www.euskalmet.euskadi.eus/media/assets/icons/euskalmet/webmet00-i{number:02}d.svg"

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/main.py (reported line 38)May include surrounding context.

python
import requests

OLD_BASE_URL = (
    "https://api.euskadi.eus/appcont/meteorologia/meteodat/images/{number:02}.png"
)
MODERN_BASE_URL = "https://www.euskalmet.euskadi.eus/media/assets/icons/euskalmet/webmet00-i{number:02}d.svg"

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The generated greeting and forecast text are always emitted in Basque, and the code also selects the BASQUE weather description field directly. This enforces a specific language/locale without any user opt-in or explanation, which matches the language-policy violation criteria.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script loads environment variables, reads a private API key, and prints a portion of it to stdout. Exposing even partial secrets in logs or terminal output is unnecessary for a weather skill and can aid secret discovery, correlation, or accidental leakage through CI logs, shell history capture, or shared debugging output.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code accesses a sensitive environment variable and emits partial contents without any operational safeguard, warning, or need tied to the skill's stated purpose. In practice this can leak credentials into logs, observability systems, screenshots, or support transcripts, increasing the chance of unauthorized API use.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest describes a tool for obtaining weather forecasts, temperatures, and general forecast information. However, the documented behavior also includes testing API credentials, downloading weather icons, and adding personalized greetings, which go beyond the narrowly described forecast-use purpose.

Content

No source excerpt is available for this finding.