Back to skill

Security audit

Fin Intel Hub

Security checks for vulnerabilities and agentic risk

Overview

This finance data skill is mostly purpose-aligned, but it needs review because optional API keys can be exposed through raw error output despite documentation claiming sensitive data is safely redacted.

Review before installing if you plan to configure paid or quota-limited API keys. Prefer a pinned or verified installer, avoid running install commands with elevated privileges, and treat any API key that appears in logs or transcripts as exposed. The skill does not appear to trade, access financial accounts, persist background code, or perform unrelated local data collection.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/macro_data.py:51
Finding
API Keys May Be Disclosed Through Raw Exception Output<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/crypto_onchain.py:54-65, 91-92` - `scripts/macro_data.py:51-59, 88-90` - `scripts/market_data.py:101-112, 147-149` - `scripts/market_data.py:163-170, 190-192` - `scripts/market_data.py:197-203, 220-222` - `scripts/market_data.py:227-233, 254-256` - `scripts/sentiment_news.py:81-90, 115-117` **Vulnerability Type**: Sensitive credential exposure through error messages **Risk Level**: Medium ### Vulnerable Code Representative example from `scripts/macro_data.py`: ```python url = f"{self.BASE_URL}/series/observations" params = { "series_id": series_id, "api_key": self.api_key, "file_type": "json", "sort_order": "desc", "limit": 100 } if observation_start: params["observation_start"] = observation_start try: response = self.session.get(url, params=params, timeout=15) response.raise_for_status() data = response.json() observations = data.get("observations", []) if not observations: return {"series_id": series_id, "error": "No data found"} latest = None for obs in observations: if obs.get("value") and obs["value"] != ".": latest = obs break if not latest: return {"series_id": series_id, "error": "No valid data"} return { "series_id": series_id, "latest_value": float(latest["value"]), "latest_date": latest["date"], "observations": [ { "date": o["date"], "value": float(o["value"]) if o["value"] and o["value"] != "." else None } for o in observations[:30] ] } except Exception as e: print(f"FRED API error: {e}") return {"series_id": series_id, "error": str(e)} ``` Equivalent query-string credential patterns appear in the other affected clients: ```python # scripts/crypto_onchain.py params = { "a": "BTC", "s": int(start_date.timestam ...[truncated 3418 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use authentication headers instead of query-string credentials wherever the provider supports them. 2. Never print or return raw `requests` exceptions from authenticated requests. 3. Replace broad exception output with a fixed message and sanitized structured logging: ```python except requests.exceptions.RequestException as exc: logger.error( f"FRED request failed: {type(exc).__name__}" ) return { "series_id": series_id, "error": "The FRED request failed." } ``` 4. Apply `safe_api_call` or an equivalent centralized wrapper consistently to every network-facing method. 5. Add a URL-redaction function that removes credential parameters such as `api_key`, `apikey`, `apiKey`, `token`, and `access_token` before any URL is logged. 6. Ensure response bodies and provider error messages are also sanitized before logging. 7. Add automated tests that deliberately raise `HTTPError`, timeout, proxy, redirect, and connection exceptions and verify that configured secrets do not appear in captured output. 8. Rotate any API keys that may already have appeared in logs or agent transcripts. ]]>

T08 · Insecure Dependencies

Warning
Location
README.md:25
Finding
Recommended Unpinned npx Installation Executes Mutable Third-Party Code<![CDATA[ ## Vulnerability Details **File Location**: `README.md:25-29` **Vulnerability Type**: Unpinned executable installation dependency **Risk Level**: Medium ### Vulnerable Code ```markdown #### Method A: Install via Clawhub (Recommended) ```bash npx clawhub install fin-intel-hub ``` ``` ### Technical Analysis The recommended installation command invokes `npx` with an unversioned package name. Depending on the local npm environment, `npx` may download and execute the currently resolved `clawhub` package from the configured package registry. No package version, lockfile, cryptographic integrity value, or reviewed artifact digest is specified. The code executed during installation can therefore change independently of the Skill version that was audited. This creates a supply-chain trust boundary outside the reviewed project. The audited repository itself does not contain a remote payload loader and no malicious dependency was identified. The risk arises from recommending execution of a mutable third-party installer without pinning or integrity verification. ### Attack Path 1. An attacker compromises the package publication account, registry resolution path, or a future package release. 2. The attacker publishes a malicious version under the package name resolved by `npx`. 3. A user follows the README's recommended installation command. 4. `npx` downloads the current package version from the configured registry. 5. Package lifecycle or CLI code executes with the installing user's permissions. 6. The malicious installer can perform any action available to that user, independently of the reviewed Skill code. ### Impact Assessment If the externally resolved installer is compromised, it can execute arbitrary code with the privileges of the user running `npx`. Potential impact includes: - Reading files and credentials accessible to the user. - Modifying the user's Skill installation or configuration. - Installing persistence in user-writable startup loc ...[truncated 253 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the installer to a specifically reviewed version: ```bash npx --yes clawhub@<reviewed-version> install fin-intel-hub ``` 2. Publish and document the expected package provenance, registry, version, and integrity digest. 3. Use npm lockfiles and integrity metadata where installation is performed through a managed project. 4. Prefer downloading a signed or checksummed release archive when executable installer behavior is unnecessary. 5. Document how users can verify release signatures or SHA-256 hashes before installation. 6. Advise users not to run the installer with administrative privileges. 7. Periodically re-audit the pinned installer before updating the recommended version. ]]>

T08 · Insecure Dependencies

Note
Location
scripts/yahoo_finance.py:1
Finding
Yahoo Finance Module Imports an Undeclared and Unused Third-Party Dependency<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/yahoo_finance.py:1-4` - Contradictory dependency declaration: `SKILL.md:27` **Vulnerability Type**: Undeclared dependency and unnecessary supply-chain surface **Risk Level**: Low ### Vulnerable Code From `scripts/yahoo_finance.py`: ```python import requests import pandas as pd from datetime import datetime, timedelta from typing import Dict, List, Optional, Any ``` From `SKILL.md`: ```yaml requirements: | No pip packages required. Uses only Python standard library + requests. ``` ### Technical Analysis The Yahoo Finance module imports `pandas`, but no reviewed code in the module uses the `pd` alias. The declared requirements state that only the standard library and `requests` are needed. Because Python resolves imports when the module is loaded, a clean environment matching the documented requirements will fail to import `scripts.yahoo_finance` if pandas is absent. Users may respond by installing an undocumented and unpinned package manually, expanding the dependency and supply-chain surface unnecessarily. No malicious pandas package or dependency-confusion package was found in the project. The confirmed issue is the mismatch between implementation and declared dependencies, combined with the fact that the dependency is unnecessary. ### Attack Path 1. A user installs the Skill according to its stated requirements. 2. The user invokes the advertised Yahoo Finance functionality. 3. Python attempts to execute `import pandas as pd`. 4. If pandas is not installed, module loading fails before any Yahoo functionality can run. 5. The user may install pandas ad hoc without a project-controlled version or integrity policy. 6. Installation from an untrusted index, typo, compromised package source, or unsafe dependency chain may introduce additional supply-chain risk. ### Impact Assessment The immediate confirmed impact is loss of availability for the Yahoo Finance functionality in environment ...[truncated 311 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Remove the unused import: ```python import requests from datetime import datetime, timedelta from typing import Dict, List, Optional, Any ``` Additionally: 1. Add a dependency manifest that explicitly declares every required third-party package. 2. Pin or constrain dependency versions according to the project's release policy. 3. Add a clean-environment test that imports every shipped module using only declared dependencies. 4. Use static analysis to reject unused imports and prevent similar dependency drift. 5. If pandas becomes necessary in the future, document why it is required and include it in a reviewed, reproducible dependency specification. ]]>
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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (18)

Rp1

Medium
Category
MCP Rug Pull
Confidence
84% confidence
Finding
The README instructs users to run `npx clawhub install fin-intel-hub` without pinning a specific `clawhub` version. This creates a supply-chain risk because `npx` will fetch the latest package at execution time, so a compromised, typosquatted, or malicious future release could execute arbitrary code on the user's system during installation. In a skill-installation context, this is more dangerous because users are explicitly encouraged to run the command locally.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
This markdown file is entirely presented in Simplified and Traditional Chinese, with no English or explicit user-selectable language option in the document itself. The policy for natural-language violations applies to all file types and flags cases where a skill enforces a specific language without user opt-in.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
The README instructs users to run `npx clawhub install fin-intel-hub` without pinning a specific `clawhub` version. Because `npx` resolves and executes the latest published package by default, a compromised upstream package, typo-squatted replacement, or breaking update could cause users to run unintended code during installation.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
This is a second unpinned `npx clawhub` execution path in the Traditional Chinese installation section. It carries the same supply-chain risk: users may execute whatever version is currently served, including a malicious or compromised release, directly on their system.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The skill description explicitly includes a catch-all trigger for 'any financial data research and analysis tasks,' which is broader than the concrete capabilities listed elsewhere. Overly broad routing language can cause the agent to invoke this skill for loosely related requests, increasing the chance of unnecessary external data access, unexpected behavior, or the skill being selected in contexts it was not designed to handle safely.

External Transmission

Medium
Category
Data Exfiltration
Content
end_date = datetime.now()
        start_date = end_date - timedelta(days=days)
        
        url = "https://api.glassnode.com/v1/metrics/flows/exchange_inflow"
        params = {
            "a": "BTC",
            "s": int(start_date.timestamp()),
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
"""Fallback: Get exchange data from CoinGecko (limited but free)."""
        try:
            # CoinGecko exchange volume data as proxy
            url = "https://api.coingecko.com/api/v3/exchanges"
            response = self.session.get(url, timeout=10)
            
            if response.status_code != 200:
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
"""Fallback: Get exchange data from CoinGecko (limited but free)."""
        try:
            # CoinGecko exchange volume data as proxy
            url = "https://api.coingecko.com/api/v3/exchanges"
            response = self.session.get(url, timeout=10)
            
            if response.status_code != 200:
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
"""
        try:
            if protocol:
                url = f"https://api.llama.fi/protocol/{protocol.lower()}"
            else:
                url = "https://api.llama.fi/charts"
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
"""
        try:
            if protocol:
                url = f"https://api.llama.fi/protocol/{protocol.lower()}"
            else:
                url = "https://api.llama.fi/charts"
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
if not etherscan_key:
            # Fallback to public gas tracker
            try:
                url = "https://api.etherscan.io/api"
                params = {
                    "module": "gastracker",
                    "action": "gasoracle",
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
try:
            # Whale Alert API integration would go here
            # https://api.whale-alert.io/v1/transactions
            pass
        except Exception as e:
            print(f"Whale alert error: {e}")
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
class FREDClient:
    """Client for fetching macroeconomic data from FRED (Federal Reserve Economic Data)."""
    
    BASE_URL = "https://api.stlouisfed.org/fred"
    
    def __init__(self, api_key: Optional[str] = None):
        """
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
if not cik:
            return []
        
        url = f"https://data.sec.gov/api/xbrl/companyfacts/CIK{cik}.json"
        
        try:
            response = self.session.get(url, timeout=15)
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
if not cik:
            return []
        
        url = f"https://data.sec.gov/api/xbrl/companyfacts/CIK{cik}.json"
        
        try:
            response = self.session.get(url, timeout=15)
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
This is a real information disclosure weakness. Although the logger sanitizes only the explicit message string, the code returns raw exception text to callers for RateLimitExceeded and ValidationError via `{"error": str(e) ...}`, and those exceptions may contain user input, URLs, tokens, or upstream error details. In a finance-data skill that handles API calls and external inputs, this can leak sensitive operational details or attacker-supplied content into user-visible responses and logs.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The request parameters hard-code `"language": "en"`, which constrains the skill to English content regardless of user preference. This is a natural-language/locale policy concern because the file provides no user choice, opt-in, or documented region-specific justification for the restriction.

Missing User Warnings

Low
Confidence
84% confidence
Finding
This code reads sensitive API keys from environment variables and sends them in outbound HTTP requests, but provides no confirmation prompt or user-facing disclosure before transmitting them. Although the docstrings mention API usage, they do not clearly warn that locally configured credentials will be attached to requests.

Static analysis

No suspicious patterns detected.