Back to skill

Security audit

Yr Weather

Security checks for vulnerabilities and agentic risk

Overview

The skill's weather lookup behavior is mostly coherent, but its documentation recommends an unpinned Git-based pip install that can run mutable external code.

Review this before installing. The local skill code is a simple MET Norway weather client, but avoid the documented unpinned Git install unless you trust that repository and build chain; prefer a reviewed commit hash or verified release artifact. Also be aware that latitude, longitude, and optional altitude are sent to MET Norway when fetching forecasts.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:60
Finding
Mutable Git Installation and Unpinned Build Backend Permit Supply-Chain Code Execution<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:60-64`; `pyproject.toml:1-3` **Vulnerability Type**: Unpinned and mutable installation-time dependencies **Risk Level**: Medium ### Vulnerable Code `SKILL.md:60-64`: ```markdown ## Standalone Repo Install via pip: `pip install git+https://github.com/brandoncrabpi/yr-weather.git` - `yr-weather -33.9288 18.4174` - Tagged: v1.0.0 ``` `pyproject.toml:1-3`: ```toml [build-system] requires = ["hatchling"] build-backend = "hatchling.build" ``` ### Technical Analysis The documented Git installation command does not pin the package to the advertised `v1.0.0` tag or, preferably, an immutable commit hash. Pip therefore retrieves the current state of the repository's default branch. The code installed and built may consequently differ from the version that was audited. The build-system dependency also specifies `hatchling` without an exact version or reviewed constraint. During package installation, pip resolves and executes the selected build backend. This gives mutable upstream build tooling an installation-time code-execution opportunity. No malicious payload was found in the reviewed project. The vulnerability is the inability to guarantee that future executions of the documented installation process will retrieve and run the reviewed code. ### Attack Path 1. An attacker compromises the referenced GitHub repository, its maintainer account, the package source used to resolve `hatchling`, or another relevant supply-chain component. 2. The attacker publishes malicious repository content or a malicious dependency version. 3. A user or Agent follows the documented command: ```bash pip install git+https://github.com/brandoncrabpi/yr-weather.git ``` 4. Pip retrieves the mutable default branch and resolves the unconstrained build backend. 5. The compromised build or package code executes during installation or later through the installed command-line entry points. 6. The malicious code operate ...[truncated 777 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin Git installations to a reviewed immutable full commit SHA: ```bash pip install "git+https://github.com/brandoncrabpi/yr-weather.git@FULL_REVIEWED_COMMIT_SHA" ``` 2. If a release tag is documented for usability, verify that the tag is protected and signed. A commit SHA should still be preferred because ordinary Git tags can be moved. 3. Pin the build backend to a reviewed version: ```toml [build-system] requires = ["hatchling==REVIEWED_VERSION"] build-backend = "hatchling.build" ``` 4. Use a controlled dependency-locking process with cryptographic hashes where supported. Retrieve dependencies only from explicitly trusted indexes. 5. Build wheels in an isolated, restricted environment and publish reviewed artifacts with checksums or signatures. Recommend installing the verified wheel instead of building mutable repository content directly. 6. Add automated dependency review, provenance verification, and periodic checks for unexpected changes to release tags, build dependencies, and package ownership. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (10)

YARA rule 'agent_skill_remote_bootstrap_execution': Remote script or code download followed by execution/bootstrap installation [agent_skills]

High
Category
YARA Match
Content
35.6762  | 139.6503 |

## Structure

```
scripts/
├── yr_service.py    # API calls (tested/mocked)
├── utils.py         # Emoji/symbol helpers
├── weather.py       # Current + forecast CLI
├── tomorrow.py      # Tomorrow summary CLI
└── tests/data/      # Sample JSON
tests/
├── test_weather.py
└── test_service.py
```

## Standalone Repo

Install via pip: `pip install git+https://github.com/brandoncrabpi/yr-weather.git`
- `yr-weather -33.9288 18.4174`
- Tagged: v1.0.0

## Usage Terms

- User-Agent required (included).
- Cache 10min+ per location.
- Credit: "Data from MET Norway".

Refactored for production: no defaults, tests, modular service.
Confidence
94% confidence
Finding
The documentation instructs installation directly from a remote Git repository via pip, which introduces a software supply-chain risk. If the referenced repository, tag, dependency chain, or transport context is compromised, users may fetch and run unreviewed code; in a skill context, normalizing remote bootstrap commands makes this pattern more dangerous.

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill advertises and instructs use of network-capable scripts but does not declare any explicit tool scope or permissions boundary. In an agent ecosystem, this can lead to undeclared outbound requests being available to the skill, reducing transparency and making policy enforcement harder.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The manifest says to use the skill when the user asks for "weather information, forecasts, temperature, precipitation, wind conditions, or any weather-related queries for specific locations." This is a very broad activation description without explicit exclusions or narrower trigger boundaries, which could cause unintended invocation on common conversation about weather.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The file-level and function documentation say this script provides tomorrow's weather output, but the range calculation iterates over `tomorrow_entries` as if each item already contained a `temp` field. Earlier code shows `tomorrow_entries` contains raw API entries and temperature is nested under `entry['data']['instant']['details']`, so this line will fail instead of formatting the advertised forecast output.

External Transmission

Medium
Category
Data Exfiltration
Content
mock_response.__enter__.return_value = mock_response  # Fix context manager

        data = get_location_forecast(-33.9288, 18.4174)
        expected_url = "https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=-33.9288&lon=18.4174"
        self.assertIn(expected_url, mock_urlopen.call_args[0][0].get_full_url())

    @unittest.mock.patch('urllib.request.urlopen')
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
mock_response.__enter__.return_value = mock_response  # Fix context manager

        data = get_location_forecast(-33.9288, 18.4174)
        expected_url = "https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=-33.9288&lon=18.4174"
        self.assertIn(expected_url, mock_urlopen.call_args[0][0].get_full_url())

    @unittest.mock.patch('urllib.request.urlopen')
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
mock_response.__enter__.return_value = mock_response  # Fix context manager

        data = get_location_forecast(-33.9288, 18.4174)
        expected_url = "https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=-33.9288&lon=18.4174"
        self.assertIn(expected_url, mock_urlopen.call_args[0][0].get_full_url())

    @unittest.mock.patch('urllib.request.urlopen')
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Unverifiable Dependency: pytest has 2 known advisory(ies) (CVE-2025-71176 (pytest has vulnerable tmpdir handling); CVE-2025-71176 (pytest has vulnerable tmpdir handling)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Missing User Warnings

Low
Confidence
79% confidence
Finding
This Python code file makes a network call via get_location_forecast(args.lat, args.lon), which likely transmits the user-provided location to an external service. While the module docstring and CLI description say the tool gets weather from Yr.no, there is no explicit runtime disclosure, confirmation, or warning that coordinates will be sent to a remote service.

Missing User Warnings

Low
Confidence
84% confidence
Finding
This CLI sends user-supplied latitude/longitude to an external weather service without any explicit user-facing disclosure in this file. While expected for a weather skill, location data can still be privacy-sensitive, so the lack of notice is a real but low-severity privacy issue rather than a code-execution or system-compromise flaw.

Static analysis

No suspicious patterns detected.