Back to skill

Security audit

DISTRICT9

Security checks for vulnerabilities and agentic risk

Overview

This skill can autonomously spend real BNB to launch tokens and lacks adequate live-transaction safeguards, with real-looking credentials also shipped in a PoC file.

Review this carefully before installing. Use only a fresh low-balance wallet, rotate or ignore the shipped PoC credentials, prefer testnet or dry-run first, and do not run openclaw start on mainnet unless you are comfortable with autonomous irreversible token deployments, gas spending, metadata publication, and initial buys without a confirmation prompt.

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

T09 · Insecure Skill Coding Practices

Error
Location
poc/d9_launch.py:20
Finding
Hardcoded Wallet Private Key and OpenRouter API Key## Vulnerability Details **File Location**: `poc/d9_launch.py:20-23` **Vulnerability Type**: Plaintext hardcoded credentials **Risk Level**: Critical ### Vulnerable Code ```python # ============ Configuration ============ PRIVATE_KEY = "0xa1007620c8d030e613759de8ac18865799ab798e2447dd28893cbdc015b79cd1" OPENROUTER_API_KEY = "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" ``` The credentials are subsequently used in security-sensitive operations: ```python headers = { "Authorization": f"Bearer {OPENROUTER_API_KEY}", "Content-Type": "application/json", } ``` ```python account = Account.from_key(PRIVATE_KEY) ``` ### Technical Analysis The source contains a complete Ethereum-compatible private key and a complete OpenRouter API key in plaintext. Repository access is therefore equivalent to access to both credentials. The private key is loaded into an account and used to sign BSC mainnet token-deployment and initial-purchase transactions. It is not directly transmitted by the code, but possession of the committed value is sufficient for any party to independently sign arbitrary transactions for the associated wallet. The OpenRouter key is placed in an HTTP `Authorization` header and sent to the configured OpenRouter endpoint. It can be reused outside this project to consume the account's API quota or incur charges. ### Attack Path 1. An attacker obtains the repository, a source archive, a package containing the PoC, or an older commit. 2. The attacker copies the private key and imports it into a Web3-compatible wallet. 3. The attacker derives the associated public address and checks its balances and token approvals. 4. The attacker signs arbitrary transfers or contract calls, potentially draining all assets controlled by the key. 5. Independently, the attacker copies the OpenRouter API key and submits API requests billed to the affected account. 6. Removing the ...[truncated 613 chars]
Remediation
## Remediation Suggestions 1. Immediately revoke and rotate the OpenRouter API key. 2. Permanently abandon the exposed wallet key. Transfer remaining assets and permissions to a newly generated wallet using a key that has never appeared in source control. 3. Replace hardcoded values with environment-variable or secret-manager references: ```python private_key = os.environ["OPENCLAW_WALLET_KEY"] api_key = os.environ["OPENROUTER_API_KEY"] ``` 4. Purge the credentials from the complete Git history and any published packages, archives, logs, caches, forks, and CI artifacts. Rotation remains mandatory because history rewriting cannot invalidate copied credentials. 5. Add automated secret scanning to pre-commit hooks and CI. 6. Use a dedicated, minimally funded launch wallet rather than a wallet containing unrelated assets. 7. Scope API credentials to the minimum available permissions and configure provider-side spending limits and alerts.

T09 · Insecure Skill Coding Practices

Error
Location
openclaw/sensing/news.py:29
Finding
Untrusted RSS Content Influences Autonomous Mainnet Transactions## Vulnerability Details **File Locations**: - `openclaw/sensing/news.py:29-55` - `openclaw/brain/synthesizer.py:35-43` - `openclaw/brain/prompts.py:20-43` - `openclaw/agent.py:87-140` - `openclaw/brain/evaluator.py:21-40` **Vulnerability Type**: Indirect prompt injection in an autonomous financial workflow **Risk Level**: High ### Vulnerable Code External RSS content is collected without establishing an instruction/data boundary: ```python resp = requests.get(url, timeout=10, headers={ "User-Agent": "OpenClaw/0.1 (DISTRICT9 Agent)" }) resp.raise_for_status() root = ET.fromstring(resp.content) signals = [] items = root.findall(".//item")[:10] for item in items: title = item.findtext("title", "") desc = item.findtext("description", "") if not title: continue score = self._score_headline(title, desc) if score > 30: signals.append(Signal( source="news", keyword=title[:80], score=score, context=f"[{source_name}] {title}. {desc[:200]}", )) ``` The content is directly interpolated into an LLM prompt: ```python signals_text = "\n".join( f"- [{s.source}] {s.keyword} (relevance: {s.score:.0f}/100)\n {s.context}" for s in signals[:10] ) system = SYSTEM_SYNTHESIZER.format(user_strategy=self.strategy.prompt) user = USER_SYNTHESIZER.format(signals=signals_text, count=count) raw = self.llm.generate_json(system, user, temperature=0.9) ``` Generated output can proceed to a real launch without human approval: ```python best = self.evaluator.select_best(concepts) if not best: log.info("No concept scored high enough.") return if self.dry_run: return result = self.launcher.launch(metadata, image_path=logo_path) ``` The acceptance threshold is only 50: ```python def select_best(self, concepts: list[MemeConcept], min_score: float = 50) -> MemeCo ...[truncated 2180 chars]
Remediation
## Remediation Suggestions 1. Require explicit human approval for every mainnet deployment and purchase. Display the complete decoded transaction, destination contracts, value, token metadata, fee recipients, and estimated maximum fee. 2. Treat feed content as untrusted data. Enclose it in explicit data delimiters and add a system-level rule that instructions found inside signal data must never be followed. 3. Prefer structured fields and strip markup, control characters, instruction-like blocks, URLs, and excessive content before prompting. 4. Validate generated output deterministically: - Strictly bound name and symbol lengths and character sets. - Apply content and trademark policies. - Bound every numeric score to `0-100`. - Reject URLs or instruction text in generated fields where not required. 5. Do not use an LLM as the sole approval control. Add deterministic policy checks and an independent transaction authorization layer. 6. Fail closed when evaluation fails instead of retaining the model-provided initial score. 7. Use testnet by default and isolate the launch wallet with a low balance and explicit daily value limit. 8. Record the source content, generated output, policy results, and human approval in an audit log before broadcasting.

T09 · Insecure Skill Coding Practices

Error
Location
openclaw/config.py:84
Finding
Arbitrary LLM Base URL Can Receive the Configured API Credential## Vulnerability Details **File Locations**: - `openclaw/config.py:84-103` - `openclaw/brain/llm.py:37-48` - `openclaw/creator/logo_gen.py:76-92` **Vulnerability Type**: Credential disclosure through an unrestricted configurable endpoint **Risk Level**: High ### Vulnerable Code The configuration accepts an unrestricted base URL: ```python llm_cfg = raw["strategy"]["llm"] llm_key_env = llm_cfg["api_key_env"] llm_key = _resolve_env(llm_key_env, "LLM API key") llm=LLMConfig( provider=llm_cfg.get("provider", "openai"), model=llm_cfg.get("model", "gpt-4o-mini"), api_key=llm_key, base_url=llm_cfg.get("base_url"), ), ``` The text client forwards the API key to that endpoint: ```python base_url = self.base_url if not base_url: if self.provider == "openrouter": base_url = "https://openrouter.ai/api/v1" client = OpenAI(api_key=self.api_key, base_url=base_url) resp = client.chat.completions.create( model=self.model, messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ], temperature=temperature, ) ``` The image client explicitly places the same key in an authorization header: ```python base = self.base_url or "https://openrouter.ai/api/v1" url = f"{base}/chat/completions" headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", } resp = requests.post( url, headers=headers, json={ "model": model, "messages": [{"role": "user", "content": prompt}], "modalities": ["image", "text"], }, timeout=90, ) ``` ### Technical Analysis `base_url` is read from YAML without validating the scheme, hostname, port, or relationship to the selected provider. Consequently, the application can send its bearer credential to any server named in the configuration. Plaintext HTTP is not expl ...[truncated 1469 chars]
Remediation
## Remediation Suggestions 1. Bind each provider to an explicit allowlist of HTTPS origins, such as the official OpenAI, Anthropic, or OpenRouter endpoint. 2. Reject non-HTTPS URLs, embedded user information, unexpected ports, fragments, and non-public or loopback destinations unless a separate, explicitly trusted local-provider mode is enabled. 3. Validate the final destination after redirects and reject redirects to a different origin. 4. Do not reuse a provider credential with arbitrary OpenAI-compatible endpoints. Require a separate credential environment variable for each custom endpoint. 5. Warn prominently and require confirmation when a nonstandard endpoint is selected. 6. Restrict permissions on `~/.openclaw-agent/config.yaml` and reject files owned by another user or writable by group/others. 7. Add tests confirming that API authorization headers cannot be sent to unapproved hosts.

T09 · Insecure Skill Coding Practices

Error
Location
openclaw/launcher/district9.py:287
Finding
Autonomous Mainnet Spending Lacks Slippage, Amount, and Confirmation Safeguards## Vulnerability Details **File Locations**: - `openclaw/launcher/district9.py:287-328` - `openclaw/launcher/flap.py:296-333` - `openclaw/agent.py:67-76,132-140` - `openclaw/config.py:106-112` - `SKILL.md:63-73` **Vulnerability Type**: Unsafe blockchain transaction construction and authorization **Risk Level**: High ### Vulnerable Code The District9 initial purchase sets the minimum acceptable output to zero: ```python try: gas_est = portal.functions.buy( Web3.to_checksum_address(token_addr), 0 ).estimate_gas({"from": wallet, "value": value}) gas_limit = int(gas_est * 1.3) except Exception as e: log.warning(f"Buy gas estimation failed ({e}), using 500K") gas_limit = 500_000 tx = portal.functions.buy( Web3.to_checksum_address(token_addr), 0 ).build_transaction({ "from": wallet, "value": value, "gas": gas_limit, "gasPrice": self.w3.eth.gas_price, "nonce": nonce, "chainId": self.w3.eth.chain_id, }) signed = self.w3.eth.account.sign_transaction(tx, self.account.key) tx_hash = self.w3.eth.send_raw_transaction(signed.raw_transaction) ``` Configured decimal amounts are converted through binary floating point: ```python quote_amt = self.w3.to_wei(float(self.config.launch.initial_buy), "ether") ``` Failed launch gas estimation also uses a large fallback: ```python except Exception as e: log.warning(f"Gas estimation failed ({e}), using fallback") gas_limit = 3_000_000 ``` The non-dry-run agent broadcasts without per-transaction confirmation: ```python platform = self.config.launch.platform log.info(f"Launching {best.symbol} via {platform}...") result = self.launcher.launch(metadata, image_path=logo_path) ``` ### Technical Analysis Passing `0` as `minTokensOut` removes output-price protection from the initial purchase. The transaction can succeed regardless of how few tokens are received, subject onl ...[truncated 1867 chars]
Remediation
## Remediation Suggestions 1. Default all configurations and CLI execution to testnet. 2. Require an explicit mainnet flag and interactive confirmation that displays: - Chain ID and RPC origin - Contract address and decoded function - Native value - Fee recipients - Minimum output - Maximum gas and fee 3. Require human approval for each mainnet transaction unless a separately configured and cryptographically enforced spending policy is active. 4. Parse monetary values with `decimal.Decimal` or integer wei conversion from validated decimal strings. Never pass them through `float`. 5. Enforce per-transaction, hourly, daily, and lifetime value limits in persistent state. 6. Query a trusted quote immediately before purchase and calculate a nonzero `minTokensOut` using a user-defined maximum slippage percentage. 7. Add a deadline where the contract supports one. 8. Enforce maximum gas price, priority fee, gas limit, and total transaction fee. 9. Fail closed when gas estimation fails unless the user explicitly approves a decoded transaction and fallback limit. 10. Revalidate the connected chain ID and contract bytecode against known hashes before signing.

T08 · Insecure Dependencies

Warning
Location
pyproject.toml:6
Finding
Unbounded Dependencies and Missing Lockfile Make Builds Non-Reproducible## Vulnerability Details **File Location**: `pyproject.toml:6-14` **Vulnerability Type**: Uncontrolled third-party dependency resolution **Risk Level**: Medium ### Vulnerable Code ```toml dependencies = [ "click>=8.0", "pyyaml>=6.0", "requests>=2.28", "web3>=6.0", "eth-abi>=4.0", "openai>=1.0", ] [project.optional-dependencies] anthropic = ["anthropic>=0.20"] sensors = [ "pytrends>=4.9", ] ``` The project tree supplied for audit does not contain a dependency lockfile. ### Technical Analysis Every dependency uses an open-ended lower bound and no upper bound. The documented `uv sync` installation therefore resolves whichever compatible releases are available at installation time. Two users installing the same project revision at different times can receive materially different dependency graphs. This is particularly sensitive because `web3`, `openai`, `requests`, and their transitive dependencies participate in credential-bearing network requests and blockchain transaction handling. No malicious dependency was identified in the audited declarations; the issue is the absence of reproducible, reviewed resolution. ### Attack Path 1. A future direct or transitive dependency release is compromised, malicious, or incompatibly changes security-relevant behavior. 2. A user runs the documented `uv sync` command after that release becomes eligible. 3. The resolver installs the new unreviewed version because the project specifies only a lower bound. 4. Package installation or runtime imports execute the dependency in the same user context as the Skill. 5. The dependency may consequently access process environment variables, API credentials, wallet material held in memory, files available to the process, and network connectivity. ### Impact Assessment A compromised dependency would run with the operating-system privileges of the user running the Skill. In this application cont ...[truncated 289 chars]
Remediation
## Remediation Suggestions 1. Generate and commit a reviewed `uv.lock` file covering direct and transitive dependencies. 2. Install with locked or frozen resolution in CI and production. 3. Use bounded compatible version ranges where appropriate rather than unbounded `>=` constraints. 4. Verify package hashes and obtain packages only from approved indexes. 5. Run automated vulnerability, provenance, and package-reputation checks on every dependency update. 6. Review lockfile changes as security-sensitive code changes. 7. Separate optional dependencies so installations receive only the packages necessary for enabled functionality. 8. Periodically rebuild in an isolated environment and compare the installed graph against the reviewed lockfile.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (57)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Even from the documentation alone, the skill is clearly intended to use a wallet private key, external services, and on-chain operations, yet those sensitive capabilities are not formalized as declared permissions. In an agent ecosystem, that mismatch can mislead reviewers and users about the real security boundary around transaction signing and outbound network use.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Even from the documentation alone, the skill is clearly intended to use a wallet private key, external services, and on-chain operations, yet those sensitive capabilities are not formalized as declared permissions. In an agent ecosystem, that mismatch can mislead reviewers and users about the real security boundary around transaction signing and outbound network use.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
Even from the documentation alone, the skill is clearly intended to use a wallet private key, external services, and on-chain operations, yet those sensitive capabilities are not formalized as declared permissions. In an agent ecosystem, that mismatch can mislead reviewers and users about the real security boundary around transaction signing and outbound network use.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Even from the documentation alone, the skill is clearly intended to use a wallet private key, external services, and on-chain operations, yet those sensitive capabilities are not formalized as declared permissions. In an agent ecosystem, that mismatch can mislead reviewers and users about the real security boundary around transaction signing and outbound network use.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Even from the documentation alone, the skill is clearly intended to use a wallet private key, external services, and on-chain operations, yet those sensitive capabilities are not formalized as declared permissions. In an agent ecosystem, that mismatch can mislead reviewers and users about the real security boundary around transaction signing and outbound network use.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
Even from the documentation alone, the skill is clearly intended to use a wallet private key, external services, and on-chain operations, yet those sensitive capabilities are not formalized as declared permissions. In an agent ecosystem, that mismatch can mislead reviewers and users about the real security boundary around transaction signing and outbound network use.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Even from the documentation alone, the skill is clearly intended to use a wallet private key, external services, and on-chain operations, yet those sensitive capabilities are not formalized as declared permissions. In an agent ecosystem, that mismatch can mislead reviewers and users about the real security boundary around transaction signing and outbound network use.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
Even from the documentation alone, the skill is clearly intended to use a wallet private key, external services, and on-chain operations, yet those sensitive capabilities are not formalized as declared permissions. In an agent ecosystem, that mismatch can mislead reviewers and users about the real security boundary around transaction signing and outbound network use.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
Even from the documentation alone, the skill is clearly intended to use a wallet private key, external services, and on-chain operations, yet those sensitive capabilities are not formalized as declared permissions. In an agent ecosystem, that mismatch can mislead reviewers and users about the real security boundary around transaction signing and outbound network use.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
Even from the documentation alone, the skill is clearly intended to use a wallet private key, external services, and on-chain operations, yet those sensitive capabilities are not formalized as declared permissions. In an agent ecosystem, that mismatch can mislead reviewers and users about the real security boundary around transaction signing and outbound network use.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Even from the documentation alone, the skill is clearly intended to use a wallet private key, external services, and on-chain operations, yet those sensitive capabilities are not formalized as declared permissions. In an agent ecosystem, that mismatch can mislead reviewers and users about the real security boundary around transaction signing and outbound network use.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Even from the documentation alone, the skill is clearly intended to use a wallet private key, external services, and on-chain operations, yet those sensitive capabilities are not formalized as declared permissions. In an agent ecosystem, that mismatch can mislead reviewers and users about the real security boundary around transaction signing and outbound network use.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Even from the documentation alone, the skill is clearly intended to use a wallet private key, external services, and on-chain operations, yet those sensitive capabilities are not formalized as declared permissions. In an agent ecosystem, that mismatch can mislead reviewers and users about the real security boundary around transaction signing and outbound network use.

Missing User Warnings

High
Confidence
96% confidence
Finding
The skill provides start instructions and sets `testnet: false`, while describing autonomous token deployment and an initial buy, but it does not prominently warn that running the agent can spend real funds and deploy real assets on mainnet. In this context, omission is dangerous because users may execute the command with a funded wallet and suffer irreversible on-chain transactions.

Missing User Warnings

High
Confidence
99% confidence
Finding
A hardcoded private key in source code is a severe secret-exposure issue that gives anyone with code access the ability to control the wallet and sign arbitrary transactions. In this script, that key is immediately used to deploy contracts and buy tokens on BNB Chain, so compromise can directly lead to theft of funds and unauthorized on-chain actions.

Missing User Warnings

High
Confidence
97% confidence
Finding
The deployment routine signs and broadcasts irreversible blockchain transactions without any explicit confirmation step, dry-run, or transaction preview. In the context of a token-launching skill, this is particularly dangerous because a mistaken invocation can create permanent on-chain artifacts and incur real financial loss immediately.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README explicitly promotes fully autonomous on-chain token deployment on BNB Chain but does not prominently warn that running the agent can create real blockchain transactions, spend wallet funds, and deploy irreversible assets. In this context, users may treat the tool like a harmless AI workflow and unknowingly authorize financial actions with real consequences.

Session Persistence

Medium
Category
Rogue Agent
Content
| Tax Split | 50% D9 Treasury + 50% Agent | 50% D9 Treasury + 50% Agent |
| Config | `platform: flap` | `platform: district9` |

Both modes share the same agent pipeline (sense → think → create → launch). Only the on-chain deployment path differs.

## Architecture
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The configuration example tells users to export a raw private wallet key but provides no safety guidance about key handling, wallet isolation, or the risks of exposing a hot key to an autonomous agent. Because this agent performs on-chain actions, compromise or misuse of that key can directly lead to fund loss and unauthorized transactions.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The sample configuration sets `testnet: false`, which normalizes production-chain execution without clearly warning that launches and purchases will occur on mainnet by default. In an autonomous launcher, this materially increases the chance of accidental real token deployment, gas expenditure, and treasury interactions.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill declares required environment variables and instructs users to run commands that inherently need network access, filesystem writes, and use of sensitive credentials, but it does not declare an explicit tool scope or permissions model. That omission makes the skill harder to sandbox and review, increasing the chance that an agent runtime grants broader access than users expect.

Session Persistence

Medium
Category
Rogue Agent
Content
---
name: district9
description: Autonomous meme token launcher on BNB Chain — sense trends, generate concepts, create logos, deploy tokens on-chain
homepage: https://www.district9.club
metadata:
  {
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation tells users to export a wallet private key and API key but gives no security guidance on secret handling, storage, rotation, or risks of shell history and process exposure. Because the wallet key enables direct signing of on-chain transactions, careless handling can lead to immediate theft or unauthorized token launches.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The agent automatically calls the launcher to deploy a token once its internal heuristics select a concept, with no explicit interactive confirmation, approval workflow, or secondary safety gate. In this skill’s context—an autonomous meme-token launcher operating on BNB Chain—this is materially risky because untrusted sensor/LLM outputs can directly trigger irreversible on-chain actions, spending funds and creating assets without human review.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The OpenAI-compatible path sends both system and user prompt content to a remote API, which can include user or system data. This file contains no confirmation prompt, logging, or explanatory comment/docstring warning that prompt contents are transmitted off-box to third-party services.

Static analysis

No suspicious patterns detected.