Back to skill

Security audit

Base Alpha Scanner

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed Base-chain market scanner that uses public crypto data APIs, with limited safety notes around broad routing and Basescan API-key handling.

Install only if you are comfortable with the skill sending token addresses and search terms to DexScreener, Basescan, GMGN, Clanker, Bankr, Virtuals, and related web pages. Use a dedicated, low-privilege Basescan API key, avoid putting it directly in shell history or shared CI logs, and treat its alerts as market research rather than trading advice.

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/scan_base.py:286
Finding
Basescan API Key Exposed Through Command-Line Arguments and URL Query Parameters<![CDATA[ ## Vulnerability Details **File Location**: `scripts/scan_base.py:240` and `scripts/scan_base.py:286-292` **Vulnerability Type**: API credential exposure through process arguments, shell history, and URL query parameters **Risk Level**: Medium ### Vulnerable Code ```python url = f"{BASESCAN_API}?module=token&action=tokenholderlist&contractaddress={addr}&page=1&offset=50&apikey={basescan_key}" data = fetch_json(url) ``` ```python parser.add_argument("--basescan-key", default=None, help="Basescan API key for holder data") args = parser.parse_args() # ... elif args.mode == "holders": if not args.addr: print("Error: --mode holders requires an address") sys.exit(1) scan_holders(args.addr, args.basescan_key) ``` ### Technical Analysis The script requires users to supply a Basescan API key through the `--basescan-key` command-line argument. Secrets passed through command-line arguments can be exposed through: - Shell history files. - Process inspection utilities such as `ps`, `/proc/<pid>/cmdline`, or process-monitoring software. - Job runners, orchestration systems, terminal recordings, and diagnostic logs that record complete commands. - Support bundles or CI logs containing command invocations. The key is subsequently interpolated directly into a URL query string. Although the endpoint uses HTTPS and therefore encrypts the URL in transit, query parameters may still be retained by the destination service, HTTP client instrumentation, proxies, monitoring systems, exception reports, or application logs. This implementation also conflicts with `references/api-endpoints.md`, which identifies the `BASESCAN_API_KEY` environment variable as the expected key source. The script does not read that variable. No evidence was found that the script intentionally sends unrelated sensitive local information. Its network requests target fixed services that are directly relevant to the declared on-chain scanning functionality. The network b ...[truncated 1794 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `--basescan-key` command-line option and read the key from an environment variable: ```python import os basescan_key = os.environ.get("BASESCAN_API_KEY") ``` 2. If interactive entry is required, use `getpass.getpass()` so the key is not echoed or stored in shell history: ```python from getpass import getpass basescan_key = getpass("Basescan API key: ") ``` 3. Prefer an HTTP authentication header if Basescan supports one. If the service requires an `apikey` query parameter, ensure that application logging and telemetry redact that parameter. 4. Sanitize exception messages and request diagnostics so complete URLs containing credentials are never printed or persisted. 5. Document secure secret injection for local, CI, and scheduled executions. Avoid placing the key directly in command strings, source files, or repository configuration. 6. Rotate any key previously supplied through `--basescan-key`, particularly if the script was run in shared environments, CI systems, recorded terminals, or monitored hosts. 7. Apply provider-side restrictions where available, including minimum required API permissions, rate limits, and key rotation. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
The code substantially matches part of the declared purpose: it performs Base-chain token scanning, early-launch/second-wave filtering, token deep dives, holder distribution analysis via Basescan, and some GMGN-related data retrieval. However, the description claims several additional capabilities that are not present in the supplied code, including Clanker/Bankr.fun deployment scanning, VIRTUAL Protocol monitoring, AI narrative scanning, and trade alert generation. Also, the GMGN function is weaker than described because it fetches a generic ranking endpoint rather than clearly analyzing the specific token address passed in. So while the script aligns with the general Base alpha analysis theme, the declared description materially overstates the implemented functionality.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
The code does match part of the description: it scans Clanker and Bankr.fun, monitors VIRTUAL-related launches, and runs an AI narrative scanner on Base. However, the declared purpose is much broader than the implemented behavior. The script does not perform holder analysis, smart money flow tracking, generalized on-chain analysis, or alerting, and it does not cover mainstream assets like BTC/ETH/UNI. Its true scope is a narrow CLI-based narrative-token scanner using public web APIs and DexScreener searches, not a comprehensive Base alpha intelligence skill. Therefore the description materially overstates the actual capabilities.

Lp3

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding
The skill describes workflows that rely on network-capable scripts and external web resources, but it does not declare any explicit tool scope or permissions. That creates an authorization and governance gap: an orchestrator may invoke networked behavior without clear policy boundaries, making unexpected outbound access harder to audit or restrict.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The invocation description is extremely broad, including 'any on-chain analysis task on Base chain,' which can cause the orchestration layer to select this skill for many unrelated requests. Over-broad routing increases the chance of unnecessary network calls, use of the wrong data sources, and execution outside the author's intended safety envelope.

External Transmission

Medium
Category
Data Exfiltration
Content
from datetime import datetime, timezone

DEXSCREENER_BASE = "https://api.dexscreener.com"
BASESCAN_API = "https://api.basescan.org/api"
GMGN_BASE = "https://gmgn.ai/defi/quotation/v1"

def fetch_json(url, headers=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
from datetime import datetime, timezone

DEXSCREENER_BASE = "https://api.dexscreener.com"
BASESCAN_API = "https://api.basescan.org/api"
GMGN_BASE = "https://gmgn.ai/defi/quotation/v1"

def fetch_json(url, headers=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
from datetime import datetime, timezone

DEXSCREENER_BASE = "https://api.dexscreener.com"
BASESCAN_API = "https://api.basescan.org/api"
GMGN_BASE = "https://gmgn.ai/defi/quotation/v1"

def fetch_json(url, headers=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
# Bankr API endpoints
    endpoints = [
        "https://api.bankr.bot/tokens/trending?chain=base&limit=20",
        "https://bankr.fun/api/tokens?chain=base&sort=trending&limit=20",
        "https://api.bankr.fun/v1/tokens/trending?chain=base",
    ]
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
endpoints = [
        "https://api.bankr.bot/tokens/trending?chain=base&limit=20",
        "https://bankr.fun/api/tokens?chain=base&sort=trending&limit=20",
        "https://api.bankr.fun/v1/tokens/trending?chain=base",
    ]

    data = {"error": "not tried"}
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
print("⚡ VIRTUAL Protocol — AI Agent Ecosystem\n")

    # Virtual Protocol API
    url = "https://api.virtuals.io/api/virtuals?filters[status]=DEPLOYED&sort[0]=createdAt%3Adesc&pagination[page]=1&pagination[pageSize]=20"
    data = fetch_json(url)

    if "error" in data:
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
print("⚡ VIRTUAL Protocol — AI Agent Ecosystem\n")

    # Virtual Protocol API
    url = "https://api.virtuals.io/api/virtuals?filters[status]=DEPLOYED&sort[0]=createdAt%3Adesc&pagination[page]=1&pagination[pageSize]=20"
    data = fetch_json(url)

    if "error" in data:
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
print(f"Virtual API error: {data['error']}")
        # Fallback: DexScreener search for VIRTUAL pairs
        print("Falling back to DexScreener VIRTUAL pairs...\n")
        url2 = "https://api.dexscreener.com/latest/dex/tokens/0x0b3e328455c4059EEb9e3f84b5543F74E24e7E1b"
        data2 = fetch_json(url2)
        pairs = [p for p in data2.get("pairs", []) if p.get("chainId") == "base"]
        print(f"Found {len(pairs)} VIRTUAL pairs on Base:\n")
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
print(f"Virtual API error: {data['error']}")
        # Fallback: DexScreener search for VIRTUAL pairs
        print("Falling back to DexScreener VIRTUAL pairs...\n")
        url2 = "https://api.dexscreener.com/latest/dex/tokens/0x0b3e328455c4059EEb9e3f84b5543F74E24e7E1b"
        data2 = fetch_json(url2)
        pairs = [p for p in data2.get("pairs", []) if p.get("chainId") == "base"]
        print(f"Found {len(pairs)} VIRTUAL pairs on Base:\n")
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Low
Confidence
79% confidence
Finding
The document uses natural-language instructions that hard-code a specific recipient/persona ("directing ZHAO") rather than presenting the behavior as optional or configurable. This can be a policy-style natural-language constraint because it forces a specific handling path without user opt-in or justification in the file.

Natural-Language Policy Violations

Low
Confidence
83% confidence
Finding
The heading "ZHAO's rules" and the subsequent directives prescribe a specific recipient context in natural language. Because the file does not indicate that this audience is optional, user-selected, or operationally required, it creates a policy-style constraint embedded in documentation.

Static analysis

No suspicious patterns detected.