Back to skill

Security audit

Weather Intelligence Digest Fresh

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but its optional HTML report can include unescaped weather or configuration text that could run as active content if opened or published.

Review this skill before installing if you plan to generate or publish HTML. Markdown and JSON output are consistent with the stated purpose, but the HTML path should be fixed to escape all dynamic values before use in shared, hosted, or automated contexts. Also consider pinning dependencies and using a virtual environment.

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

Error
Location
weather_digest.py:146
Finding

Stored HTML Injection Through Unescaped Dynamic Weather Data

Content
View full analysis
Expires {expiry}" if expiry else "" instructions_html = ( f"
{instructions}
" if instructions else "" ) blocks.append( f"
{event}" f"{severity}
{expiry_html}" f"
{headline}
{instructions_html}
" ) return "".join(blocks) ``` ```python city_meta = "" if report.get("city") and report.get("state"): city_meta = f"
Nearest location: {report['city']}, {report['state']}
" summary_li = "".join( f"
  • {line.replace('**', '')}
  • " for line in report["summary_lines"] ) alerts_html = format_alerts_html(report["alerts"]) cards.append( f"

    {report['display_name']}

    {city_meta}" f"

    Outlook

      {summary_li}

    Active Alerts

    {alerts_html}
    " ) ``` ### Technical Analysis The HTML renderer inserts dynamic values directly into HTML without context-appropriate escaping. The affected values include: - The locally configured location display name. - City and state values returned by the weather API. - Forecast summary values returned by the weather API. - Alert event, severity, headline, expiration, and instruction values. Removing Markdown markers with `replace('**', '')` does not sanitize HTML. Trimming alert text also does not remove tags or event-handler attributes. Consequently, a value such as `` is preserved as active HTML ...[truncated 1598 chars]
    Remediation
    View remediation
    ``` The generated document should contain escaped text such as `<img ...>`, not an active element. 6. If arbitrary markup is intentionally supported in the future, sanitize it with a maintained allowlist-based HTML sanitizer rather than relying on string replacement. ]]>

    T08 · Insecure Dependencies

    Note
    Location
    requirements.txt:1
    Finding

    Unpinned Dependency Allows Non-Reproducible Package Resolution

    Content
    View full analysis
    =2.31.0 ``` The documented installation command in `SKILL.md:16` is: ```text pip install -r requirements.txt ``` ### Technical Analysis The dependency declaration specifies only a minimum version. A fresh installation can therefore resolve to any current or future `requests` release satisfying the constraint. No lock file or package hashes are provided to verify the exact artifacts installed. No evidence indicates that `requests` is currently malicious or obtained from an unsafe package source. The issue is that installations are not reproducible and future dependency changes can be consumed without project-specific review. Transitive dependencies are also resolved dynamically. ### Attack Path 1. A user performs a fresh installation using the documented `pip install -r requirements.txt` command. 2. The package resolver selects the newest available release satisfying `requests>=2.31.0`, along with dynamically selected transitive dependencies. 3. If an allowed future release or resolved dependency is compromised, the affected package is installed without a lock-file review or hash mismatch stopping the installation. 4. Package code executes when imported or used by the application. This path depends on a future upstream or package-distribution compromise; no current malicious package was identified during the audit. ### Impact Assessment The immediate impact is non-deterministic installation behavior and reduced assurance that reviewed source corresponds to deployed dependencies. Under a successful supply-chain compromise, impact would inherit the Python process's privileges and could include access to files, network resources, and output data available to the user running the tool. The current evidence does not establish active compromis ...[truncated 99 chars]
    Remediation
    View remediation
    Vulnerability Patterns
    • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
    • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
    • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
    • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
    • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
    Findings (8)

    Undeclared Tool Scope

    Medium
    Category
    MCP Least Privilege
    Confidence
    93% confidence
    Finding

    The skill declares executable setup and usage steps that install dependencies, read configuration files, write output files, and make outbound network requests, but it does not declare any corresponding tool scope such as permissions or allowed-tools. This creates an authorization and transparency gap: an agent or reviewer cannot easily enforce least privilege, and users may invoke a skill with broader capabilities than they expected.

    Content

    No source excerpt is available for this finding.

    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 · weather_digest.py (reported line 54)May include surrounding context.

    python
    def get_point_metadata(lat: float, lon: float) -> dict:
        url = f"https://api.weather.gov/points/{lat},{lon}"
        data = fetch_json(url)
        return data["properties"]
    

    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 · weather_digest.py (reported line 85)May include surrounding context.

    python
    def get_point_metadata(lat: float, lon: float) -> dict:
        url = f"https://api.weather.gov/points/{lat},{lon}"
        data = fetch_json(url)
        return data["properties"]
    

    Tainted flow: 'markdown' from pathlib.Path.read_text (line 301, file read) → pathlib.Path.write_text (file write)

    Medium
    Category
    Data Flow
    Confidence
    65% confidence
    Finding

    Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

    Content

    Scanner excerpt · weather_digest.py (reported line 303)May include surrounding context.

    python
    reports = gather_reports(locations)
        markdown = build_markdown(reports)
        output_path = Path(args.output)
        output_path.write_text(markdown)
        print(f"Markdown digest written to {output_path}")
        if args.html_path:
            html = build_html(reports, theme=args.theme)
    

    Tainted flow: 'html' from pathlib.Path.read_text (line 306, file read) → pathlib.Path.write_text (file write)

    Medium
    Category
    Data Flow
    Confidence
    88% confidence
    Finding

    The HTML output embeds untrusted remote data from api.weather.gov directly into HTML without escaping. If the upstream feed is compromised or contains unexpected markup, opening the generated HTML could trigger script execution or content injection in the viewer's browser.

    Content

    Scanner excerpt · weather_digest.py (reported line 308)May include surrounding context.

    python
    if args.html_path:
            html = build_html(reports, theme=args.theme)
            html_path = Path(args.html_path)
            html_path.write_text(html)
            print(f"HTML digest written to {html_path} (theme: {args.theme})")
        if args.json_path:
            json_payload = build_json_document(reports)
    

    Tainted flow: 'json_payload' from pathlib.Path.read_text (line 311, file read) → pathlib.Path.write_text (file write)

    Medium
    Category
    Data Flow
    Confidence
    65% confidence
    Finding

    Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

    Content

    Scanner excerpt · weather_digest.py (reported line 313)May include surrounding context.

    python
    if args.json_path:
            json_payload = build_json_document(reports)
            json_path = Path(args.json_path)
            json_path.write_text(json.dumps(json_payload, indent=2))
            print(f"JSON digest written to {json_path}")
    

    Unpinned Dependencies

    Low
    Category
    Supply Chain
    Confidence
    92% confidence
    Finding

    The dependency is specified as requests>=2.31.0, which allows any newer release to be installed without review. This weakens build reproducibility and can unintentionally introduce vulnerable or breaking versions from the supply chain, especially because the package is used for network access in a weather-data skill.

    Content

    Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

    text
    requests>=2.31.0
    

    Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); 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) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

    Low
    Category
    Supply Chain
    Confidence
    84% confidence
    Finding

    The manifest does not pin requests to a specific version, so there is no way to verify at review time whether the deployed version avoids known advisories affecting some releases. Because this skill likely makes outbound HTTP requests to NOAA/NWS and may process user-supplied locations or endpoints indirectly, installing an affected requests release could expose it to known client-side issues such as credential leakage or TLS/request handling flaws.

    Content

    No source excerpt is available for this finding.

    Static analysis

    No suspicious patterns detected.