Back to skill

Security audit

Crypto Funding Harvester

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says: it periodically fetches public crypto funding-rate data and writes a local results file, with no evidence of credential theft or hidden behavior.

Reasonable to install if you want an automated public-market-data harvester. Run it under an unprivileged account, be aware it contacts Hyperliquid, Binance, and Bybit every 15 minutes, and consider changing the output to a private application directory instead of shared /tmp if this runs on a multi-user system.

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
funding_harvester.py:39
Finding

Predictable Temporary Output Path Allows Symlink-Based File Overwrite

Content
View full analysis

Vulnerability Details

File Location: funding_harvester.py, line 39 and lines 397–401
Vulnerability Type: Unsafe temporary-file handling and symbolic-link following
Risk Level: Medium

Vulnerable Code:

python
# Output file path
OUTPUT_PATH = "/tmp/funding_opportunities.json"
python
# 5. Save to output file
try:
    with open(OUTPUT_PATH, "w") as f:
        json.dump(output, f, indent=2)
    log.info("Results saved to %s", OUTPUT_PATH)
except OSError as e:
    log.error("Failed to write output file: %s", e)

Technical Analysis

The program repeatedly writes to a fixed, predictable pathname in the shared /tmp directory. Python's open(..., "w") follows symbolic links and truncates the resolved target before writing.

On a multi-user system, an attacker with access to /tmp may create /tmp/funding_opportunities.json as a symbolic link to another file before the scheduled process opens it. The process does not verify that the destination is a regular file, reject symbolic links, use O_NOFOLLOW, or place the output inside a private directory.

The feasibility and severity depend on operating-system protections, ownership of an existing output file, and the account under which the automaton runs. Protections such as fs.protected_symlinks may prevent some cross-user attacks, but the implementation should not rely exclusively on host-specific hardening.

Attack Path

  1. The attacker obtains local access to the shared /tmp namespace.
  2. The attacker waits until the expected output path is absent or otherwise gains the ability to replace that directory entry.
  3. The attacker creates a symbolic link:
    text
    /tmp/funding_opportunities.json -> attacker-selected target
    
  4. The scheduled automaton starts and calls open(OUTPUT_PATH, "w").
  5. The operating system resolves the symbolic link, and the process truncates and writes generated JSON to the t ...[truncated 724 chars]
Remediation
View remediation

Remediation Suggestions

  • Store output in an application-owned directory rather than the shared /tmp namespace.
  • Create that directory with restrictive permissions, such as mode 0700, and ensure it is owned by the automaton account.
  • Write to a securely created temporary file in the destination directory and publish it with an atomic os.replace.
  • Where supported, open the final destination using os.open with O_NOFOLLOW and appropriate creation flags.
  • Verify with lstat that existing destination entries are regular files owned by the expected account; note that verification alone must be designed to avoid time-of-check/time-of-use races.
  • Run the automaton as a dedicated, unprivileged account with access only to its required output directory.
  • Apply restrictive output permissions, such as mode 0600 where other users do not need to read the results.

T08 · Insecure Dependencies

Note
Location
clawhub.json:4
Finding

Unpinned Python Dependency Produces Non-Reproducible and Unsafe Installations

Content
View full analysis

Vulnerability Details

File Location: clawhub.json, lines 4–6
Vulnerability Type: Unpinned third-party dependency
Risk Level: Low

Vulnerable Code:

json
"requires": {
  "pip": ["requests"],
  "env": []
},

Technical Analysis

The project declares requests without a fixed version, version range, lockfile, or package integrity hash. Consequently, a fresh deployment may install a different dependency release from the one previously reviewed and tested.

The package name is legitimate and there is no evidence that the project intentionally references a malicious or misspelled dependency. The risk arises because future installations implicitly trust whichever release the package resolver selects from the configured package index.

If an upstream release or configured package source is compromised, dependency code can execute within the skill's Python environment. Uncontrolled upgrades can also introduce incompatible behavior or newly disclosed vulnerabilities.

Attack Path

  1. A deployment or rebuild installs dependencies from the configured Python package index.
  2. The resolver selects the latest compatible requests release because no exact version or hash is specified.
  3. A compromised, unexpectedly vulnerable, or behaviorally incompatible release is downloaded.
  4. The dependency is imported by funding_harvester.py.
  5. Any malicious import-time or request-processing behavior executes with the automaton account's privileges.

This path requires compromise or unsafe control of the upstream package source, resolver configuration, or a future dependency release; the audited files do not themselves provide such control.

Impact Assessment

A malicious dependency could access files, environment variables, network resources, and process privileges available to the automaton. This could lead to data exposure, arbitrary code execution within the skill account, or manipulation of gene ...[truncated 236 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin requests to a reviewed exact version rather than resolving an unrestricted latest version.
  • Use a lockfile that also pins transitive dependencies.
  • Require package hashes during installation, for example through a hash-locked requirements file and pip --require-hashes.
  • Retrieve packages only from an approved HTTPS package index.
  • Add automated dependency vulnerability and update monitoring.
  • Review and test version changes before updating the lockfile rather than allowing automatic uncontrolled upgrades.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (11)

Tainted flow: 'REQUEST_TIMEOUT' from os.environ.get (line 36, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · funding_harvester.py (reported line 86)May include surrounding context.

python
log.info("Fetching Hyperliquid funding rates...")
    try:
        resp = requests.post(url, json=payload, timeout=REQUEST_TIMEOUT)
        resp.raise_for_status()
        data = resp.json()
    except requests.RequestException as e:

Tainted flow: 'REQUEST_TIMEOUT' from os.environ.get (line 36, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · funding_harvester.py (reported line 151)May include surrounding context.

python
log.info("Fetching Binance funding rates...")
    try:
        resp = requests.get(url, timeout=REQUEST_TIMEOUT)
        resp.raise_for_status()
        data = resp.json()
    except requests.RequestException as e:

Tainted flow: 'REQUEST_TIMEOUT' from os.environ.get (line 36, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · funding_harvester.py (reported line 213)May include surrounding context.

python
log.info("Fetching Bybit funding rates...")
    try:
        resp = requests.get(url, params=params, timeout=REQUEST_TIMEOUT)
        resp.raise_for_status()
        data = resp.json()
    except requests.RequestException as e:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares capabilities that imply network access, environment variable use, and local file writes, but it does not explicitly scope or disclose those permissions. This is dangerous because operators cannot easily enforce least privilege or understand the full execution surface, increasing the risk of unexpected outbound requests or filesystem side effects.

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 · SKILL.md (reported line 76)May include surrounding context.

md
Returns a list of dicts with keys:
        asset, exchange, funding_rate_8h, annualized_pct, current_price
    """
    url = "https://api.hyperliquid.xyz/info"
    payload = {"type": "metaAndAssetCtxs"}

    log.info("Fetching Hyperliquid funding rates...")

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

python
Returns a list of dicts with keys:
        asset, exchange, funding_rate_8h, annualized_pct, current_price
    """
    url = "https://api.hyperliquid.xyz/info"
    payload = {"type": "metaAndAssetCtxs"}

    log.info("Fetching Hyperliquid funding rates...")

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · funding_harvester.py (reported line 86)May include surrounding context.

python
log.info("Fetching Hyperliquid funding rates...")
    try:
        resp = requests.post(url, json=payload, timeout=REQUEST_TIMEOUT)
        resp.raise_for_status()
        data = resp.json()
    except requests.RequestException as e:

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 · SKILL.md (reported line 78)May include surrounding context.

md
"""
    Fetch funding rates from Bybit linear (USDT-settled) perpetuals.

    Endpoint: GET https://api.bybit.com/v5/market/tickers?category=linear
    Returns tickers for all linear perpetual contracts including funding rate.

    We filter to USDT-settled pairs only (symbol ends with USDT).

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

python
"""
    Fetch funding rates from Bybit linear (USDT-settled) perpetuals.

    Endpoint: GET https://api.bybit.com/v5/market/tickers?category=linear
    Returns tickers for all linear perpetual contracts including funding rate.

    We filter to USDT-settled pairs only (symbol ends with USDT).

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

python
"""
    Fetch funding rates from Bybit linear (USDT-settled) perpetuals.

    Endpoint: GET https://api.bybit.com/v5/market/tickers?category=linear
    Returns tickers for all linear perpetual contracts including funding rate.

    We filter to USDT-settled pairs only (symbol ends with USDT).

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill writes output to /tmp/funding_opportunities.json but does not prominently warn users about this local persistence behavior. While the file path is documented later, omission from the high-level description can lead to surprising data persistence and weaker user consent around local writes.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.