Back to skill

Security audit

Nft Floor Price Monitor

Security checks for vulnerabilities and agentic risk

Overview

This skill is a straightforward NFT floor-price checker with optional user-enabled Discord alerts, with some privacy and credential-handling cautions but no hidden or malicious behavior found.

Install only if you are comfortable with NFT collection names, alert thresholds, floor prices, and timestamps being sent to the Discord webhook you configure. Prefer an environment variable or secret manager for the webhook URL, avoid putting it in shared command logs, and treat stderr logs as sensitive if alert delivery fails.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/floor_monitor.py:154
Finding

Discord Webhook Credential Exposure Through Exception Logging

Content
View full analysis

Vulnerability Details

File Location: scripts/floor_monitor.py, lines 154–160
Vulnerability Type: Sensitive credential exposure through error logging
Risk Level: Medium

Vulnerable Code:

python
try:
    resp = requests.post(webhook_url, json=payload, timeout=10)
    resp.raise_for_status()
    log("Discord alert sent successfully.")
    return True
except Exception as e:
    log(f"Discord alert error: {e}")
    return False

Technical Analysis

The script sends alert data to a Discord webhook URL and logs the raw exception if the request fails. A Discord webhook URL contains a secret token that authorizes messages to the associated channel.

Exceptions generated by the requests library may include the complete request URL in their string representation. For example, an HTTP error raised by raise_for_status() can identify the URL that returned the unsuccessful status. Consequently, the exception logged to standard error may contain the webhook credential.

This behavior is not necessary for the declared alert functionality and violates least-disclosure principles. The alert request itself is expected and user-enabled, but exposing its authentication URL in logs exceeds the minimum information required for diagnostics.

Attack Path

  1. A user configures a Discord webhook through --discord-webhook or DISCORD_WEBHOOK_URL.
  2. An alert condition is triggered while the --discord option is enabled.
  3. The webhook request fails because of an HTTP error, connectivity problem, proxy response, revoked webhook, or deliberately induced network failure.
  4. The broad exception handler converts the resulting exception to text.
  5. The script writes that text to standard error without sanitization.
  6. A party with access to process, CI/CD, agent, service, or centralized logging output obtains the complete webhook URL if it appears in the exception.
  7. The party uses the webhook token t ...[truncated 702 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not log the raw exception where a credential-bearing URL may be attached. Emit a fixed diagnostic message and, if needed, the exception class:

    python
    except requests.RequestException as exc:
        log(f"Discord alert failed: {type(exc).__name__}")
        return False
    
  2. If HTTP status information is needed, log only a sanitized numeric status code:

    python
    except requests.HTTPError as exc:
        status = exc.response.status_code if exc.response is not None else "unknown"
        log(f"Discord alert failed with HTTP status {status}")
        return False
    except requests.RequestException as exc:
        log(f"Discord alert failed: {type(exc).__name__}")
        return False
    
  3. Never include the webhook URL, request headers, response body, or serialized request object in diagnostics.

  4. Validate webhook destinations before transmission:

    • Require HTTPS.
    • Restrict the hostname to approved Discord webhook domains.
    • Reject URLs containing unexpected user information, fragments, or malformed paths.
    • Disable redirects or revalidate every redirect destination to prevent alert data from being forwarded to an unintended host.
  5. Treat existing logs as potentially compromised. Search retained logs for Discord webhook URL patterns, restrict log access, remove exposed values where feasible, and revoke and regenerate any webhook whose URL may have been recorded.

  6. Prefer runtime secret injection through a protected environment or secret manager, and ensure command-line arguments containing webhook URLs are discouraged because command lines may be visible in process listings and execution logs.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Tainted flow: 'webhook_url' from os.getenv (line 125, 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 · scripts/floor_monitor.py (reported line 149)May include surrounding context.

python
}

    try:
        resp = requests.post(webhook_url, json=payload, timeout=10)
        resp.raise_for_status()
        log("Discord alert sent successfully.")
        return True

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger list is broad and includes generic phrases like "floor price," "NFT alert," and "NFT portfolio," which can cause the skill to activate in ordinary NFT discussions rather than only when the user explicitly wants monitoring or alerting behavior. Over-broad activation increases the chance of unintended execution, unnecessary external API calls, and accidental prompting toward Discord-based data transmission.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill documents sending alerts via Discord webhook but does not clearly warn users that collection names, price thresholds, and timing/event data will be transmitted to a third-party service outside the local environment. This can lead to unintended disclosure of trading interests or operational metadata, especially if users provide personal or private webhook endpoints without understanding the data flow.

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 · scripts/floor_monitor.py (reported line 19)May include surrounding context.

python
# ── API Endpoints ──────────────────────────────────────────────────────────────

# OpenSea API v2 (REST)
OPENSEA_V2_COLLECTION = "https://api.opensea.io/api/v2/collections/{slug}"

# OpenSea API v1 (fallback)
OPENSEA_V1_COLLECTION = "https://api.opensea.io/api/v1/collection/{slug}"

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/floor_monitor.py (reported line 22)May include surrounding context.

python
# ── API Endpoints ──────────────────────────────────────────────────────────────

# OpenSea API v2 (REST)
OPENSEA_V2_COLLECTION = "https://api.opensea.io/api/v2/collections/{slug}"

# OpenSea API v1 (fallback)
OPENSEA_V1_COLLECTION = "https://api.opensea.io/api/v1/collection/{slug}"

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/floor_monitor.py (reported line 25)May include surrounding context.

python
OPENSEA_V1_COLLECTION = "https://api.opensea.io/api/v1/collection/{slug}"

# CoinGecko simple crypto price (for ETH/USD conversion reference)
COINGECKO_SIMPLE_PRICE = "https://api.coingecko.com/api/v3/simple/price"

DISCORD_WEBHOOK_URL = os.getenv("DISCORD_WEBHOOK_URL", "")

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 · scripts/floor_monitor.py (reported line 149)May include surrounding context.

python
}

    try:
        resp = requests.post(webhook_url, json=payload, timeout=10)
        resp.raise_for_status()
        log("Discord alert sent successfully.")
        return True

Static analysis

No suspicious patterns detected.