Back to skill

Security audit

Find Arbitrage Opps

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but its setup and API credential handling are broad enough that users should review it before installing.

Install only if you are comfortable reviewing or replacing the prerequisite command and running the scanner against a trusted local Hummingbot API. Avoid running the curl-to-bash setup as-is, set explicit non-default API credentials, keep HUMMINGBOT_API_URL on localhost or HTTPS, and make sure no unintended .env file can control the API target.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
SKILL.md:17
Finding
Unpinned Remote Shell Script Download and Execution<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:17` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: Critical ### Vulnerable Code ```bash bash <(curl -s https://raw.githubusercontent.com/hummingbot/skills/main/skills/lp-agent/scripts/check_prerequisites.sh) ``` ### Technical Analysis The prerequisite instructions download a shell script from a mutable GitHub branch and pass the response directly to Bash through process substitution. The command does not pin the remote resource to an immutable commit, verify a cryptographic checksum or signature, or allow the user to inspect the downloaded content before execution. Consequently, the effective code executed by the Skill can change after the local package has been reviewed. Compromise of the upstream repository, maintainer account, branch, or content-delivery path could replace the prerequisite script with arbitrary commands. This behavior is not required to implement the declared arbitrage-scanning functionality. A local, audited prerequisite checker—or instructions that perform explicit checks without remote code execution—would provide the necessary functionality with substantially less privilege and supply-chain exposure. ### Attack Path 1. An attacker compromises the upstream repository, maintainer account, or mutable branch containing `check_prerequisites.sh`. 2. The attacker modifies the remote script to include malicious shell commands. 3. A user follows the documented prerequisite command. 4. `curl` retrieves the attacker-controlled content without integrity verification. 5. Bash immediately executes the content with the permissions of the user running the command. 6. The payload can access files and credentials available to that user, modify local state, invoke network services, or install additional payloads. ### Impact Assessment Successful exploitation provides arbitrary command execution under the invoking user's account. The accessible scope i ...[truncated 245 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Bundle the prerequisite checker inside the reviewed Skill package and execute the local copy. - If remote retrieval is unavoidable, pin the URL to an immutable commit and verify a separately trusted SHA-256 checksum or digital signature before execution. - Download the file as data, inspect and validate it, and only then execute it; do not pipe or process-substitute remote content directly into a shell. - Use `curl --fail --show-error --location` so network and HTTP failures are handled explicitly, but do not treat these options as substitutes for integrity verification. - Restrict the checker to read-only prerequisite validation and document every permission and external resource it needs. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/find_arb_opps.py:48
Finding
Basic Authentication Credentials Can Be Sent over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/find_arb_opps.py:48-67` **Vulnerability Type**: Plaintext transmission of authentication credentials **Risk Level**: High ### Vulnerable Code ```python def get_api_config(): """Get API configuration from environment.""" load_env() return { "url": os.environ.get("HUMMINGBOT_API_URL", "http://localhost:8000"), "user": os.environ.get("API_USER", "admin"), "password": os.environ.get("API_PASS", "admin"), } def api_request(method: str, endpoint: str, data: dict | None = None, timeout: int = 30) -> dict: """Make authenticated API request.""" config = get_api_config() url = f"{config['url']}{endpoint}" credentials = base64.b64encode(f"{config['user']}:{config['password']}".encode()).decode() headers = { "Authorization": f"Basic {credentials}", "Content-Type": "application/json", } ``` ### Technical Analysis The code constructs an HTTP Basic Authentication header by Base64-encoding the API username and password. Base64 is a reversible transport encoding and provides no confidentiality. The default URL uses plaintext HTTP. Although the default destination is a loopback address, `HUMMINGBOT_API_URL` is configurable and is not validated to ensure that non-loopback destinations use HTTPS. If a user or environment file sets a remote `http://` destination, the Authorization header is transmitted without transport encryption. The Base64 value is placed in an HTTP request header; it is not printed to standard output by this code. Therefore, the sensitive-data risk is network disclosure rather than stdout exfiltration. ### Attack Path 1. `HUMMINGBOT_API_URL` is configured as a remote or network-accessible `http://` endpoint, whether through user error, an untrusted environment file, or manipulated process configuration. 2. The user invokes the arbitrage scanner. 3. The script reads the API username and password and constructs ...[truncated 793 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require HTTPS whenever the configured host is not a loopback address. - Parse the API URL and reject unsupported schemes, embedded credentials, malformed hosts, and plaintext remote destinations. - If local HTTP support is necessary, explicitly permit it only for verified loopback hosts such as `127.0.0.1`, `::1`, or `localhost`. - Use a properly validated TLS context and do not disable certificate or hostname verification. - Prefer a revocable, least-privileged access token over a reusable administrator password. - Ensure redirects cannot cause an Authorization header to be sent to an unintended origin. - Remove predictable default credentials and fail securely when authentication configuration is absent. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/find_arb_opps.py:33
Finding
Overbroad Environment-File Loading and Predictable Default Credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/find_arb_opps.py:33-53` **Vulnerability Type**: Excessive secret-file access and insecure authentication defaults **Risk Level**: Medium ### Vulnerable Code ```python def load_env(): """Load environment from .env files.""" for path in ["hummingbot-api/.env", os.path.expanduser("~/.hummingbot/.env"), ".env"]: if os.path.exists(path): with open(path) as f: for line in f: line = line.strip() if line and not line.startswith("#") and "=" in line: key, value = line.split("=", 1) os.environ.setdefault(key.strip(), value.strip().strip('"').strip("'")) break def get_api_config(): """Get API configuration from environment.""" load_env() return { "url": os.environ.get("HUMMINGBOT_API_URL", "http://localhost:8000"), "user": os.environ.get("API_USER", "admin"), "password": os.environ.get("API_PASS", "admin"), } ``` ### Technical Analysis The script searches three credential-related locations and imports every assignment from the first file found into the process environment. Its declared operation only requires `HUMMINGBOT_API_URL`, `API_USER`, and `API_PASS`, so loading unrelated variables and secrets exceeds the minimum data access necessary for the task. Relative paths are resolved from the current working directory rather than a trusted project location. An unintended or attacker-controlled `.env` file can therefore influence the API URL and authentication settings when the script is launched from an untrusted directory. Existing process variables take precedence because `setdefault` is used, but absent variables can still be supplied by the file. The `admin`/`admin` fallback is predictable and may normalize unsafe API deployments. If the associated service retains matching defaults and is reachable by another user or ...[truncated 1927 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Parse only the three required keys: `HUMMINGBOT_API_URL`, `API_USER`, and `API_PASS`. - Store parsed configuration in a local dictionary instead of copying every value into `os.environ`. - Require credentials to be explicitly configured and terminate with a clear error when they are absent. - Remove the `admin`/`admin` fallback and reject known default credentials where practical. - Resolve configuration files from an explicit, trusted path rather than implicitly trusting the current working directory. - Before reading a credential file, verify that it is a regular file, is not a symbolic link where inappropriate, is owned by the expected user, and is not readable or writable by unintended users. - Clearly document configuration precedence and allow users to specify the intended file explicitly. - Validate `HUMMINGBOT_API_URL` before making any authenticated request, including enforcing HTTPS for non-loopback destinations. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Credential Access

High
Category
Privilege Escalation
Content
def load_env():
    """Load environment from .env files."""
    for path in ["hummingbot-api/.env", os.path.expanduser("~/.hummingbot/.env"), ".env"]:
        if os.path.exists(path):
            with open(path) as f:
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
def load_env():
    """Load environment from .env files."""
    for path in ["hummingbot-api/.env", os.path.expanduser("~/.hummingbot/.env"), ".env"]:
        if os.path.exists(path):
            with open(path) as f:
                for line in f:
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill invokes network-capable commands and relies on environment variables, but it does not declare any tool scope or permissions boundaries. This is dangerous because an agent or runner may execute external network requests and access sensitive local configuration or credentials without explicit user-visible authorization, increasing the risk of unintended data exposure or unsafe command execution.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The script performs authenticated network requests automatically using credentials loaded from environment or local .env files, but it provides no user-facing disclosure that credentials will be used or that remote requests will be sent. In a skill context, this can surprise users and cause unintended credential use against a configured API endpoint, especially because the endpoint is environment-controlled and may not be localhost in practice.

Static analysis

No suspicious patterns detected.