Back to skill

Security audit

BAP-578 BAP-tism

Security checks for vulnerabilities and agentic risk

Overview

This skill fits its Web3 agent-onboarding purpose, but it needs review because it asks agents to persist wallet secrets and perform high-impact blockchain and social actions with weak safeguards.

Install only after treating this as hot-wallet automation. Use a low-value dedicated wallet, do not store seed phrases or private keys in plaintext, avoid treasury keys unless absolutely necessary, prefer direct official APIs or explicitly trust the proxy, pin dependencies, and require local review or simulation before signing transactions or posting publicly.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:150
Finding
Wallet Private Key and Recovery Mnemonic Stored in Plaintext## Vulnerability Details **File Location**: `SKILL.md`, lines 150-164 **Vulnerability Type**: Plaintext storage of wallet credentials **Risk Level**: High ### Vulnerable Code ```python WALLET_FILE = "agent_wallet.json" def get_or_create_wallet(): """Get existing wallet or create new one (ONCE per agent!)""" if os.path.exists(WALLET_FILE): with open(WALLET_FILE, 'r') as f: return json.load(f) # First time only - create new wallet Account.enable_unaudited_hdwallet_features() acct, mnemonic = Account.create_with_mnemonic() wallet = { "address": acct.address, "private_key": acct.key.hex(), "seed_phrase": mnemonic } # Save permanently with open(WALLET_FILE, 'w') as f: json.dump(wallet, f) ``` The same insecure storage pattern is repeated in `SKILL.md` at lines 1045-1059. ### Technical Analysis The Skill writes both the wallet private key and its recovery mnemonic to the predictable relative path `agent_wallet.json`. The data is serialized as unencrypted JSON, and the code does not apply restrictive file permissions, encryption, an operating-system credential store, or a dedicated secret-management mechanism. A mnemonic and private key each provide complete control of the wallet. Storing both credentials together increases exposure without providing a security benefit. The relative path also makes the file likely to reside in an application workspace that may be accessible to other skills, local processes, backup tools, support bundles, or source-control operations. The Skill's declared blockchain functionality requires signing access, but it does not require permanent plaintext storage of two equivalent root credentials. This behavior therefore exceeds the minimum safe privilege and secret-retention requirements. ### Attack Path 1. The user or agent invokes the wallet-creation example. 2. ...[truncated 1060 chars]
Remediation
## Remediation Suggestions - Do not retain the recovery mnemonic after initial wallet provisioning. - Store signing credentials in a platform secret manager, hardware-backed wallet, or encrypted Web3 keystore. - Encrypt credentials with a user-supplied secret that is not stored alongside the encrypted data. - Create credential files atomically with owner-only permissions, such as mode `0600`. - Prevent wallet files from being included in repositories, logs, backups, support bundles, or model context. - Separate transaction construction from signing and require explicit authorization for value-bearing or privilege-granting transactions. - Document a credential-rotation and wallet-migration procedure for suspected exposure.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
SKILL.md:384
Finding
Wallet Authentication and Token-Creation Data Delegated to an Unnecessary Third-Party Proxy## Vulnerability Details **File Location**: `SKILL.md`, lines 384-466 **Vulnerability Type**: Excessive delegation of wallet-authenticated operations **Risk Level**: High ### Vulnerable Code ```python FOURMEME_PROXY = "https://bapbook-api.fly.dev/api/fourmeme" w3 = Web3(Web3.HTTPProvider("https://bsc-dataseed.binance.org/")) account = Account.from_key(wallet["private_key"]) # Get nonce nonce_res = requests.post(f"{FOURMEME_PROXY}/nonce", json={ "accountAddress": wallet["address"] }) nonce_data = nonce_res.json() if not nonce_data.get("success"): raise Exception(f"Nonce failed: {nonce_data}") nonce = nonce_data["nonce"] # Sign message and login message = f"You are sign in Meme {nonce}" message_hash = encode_defunct(text=message) sig = account.sign_message(message_hash) login_res = requests.post(f"{FOURMEME_PROXY}/login", json={ "address": wallet["address"], "signature": sig.signature.hex() }) login_data = login_res.json() if not login_data.get("success"): raise Exception(f"Login failed: {login_data}") access_token = login_data["accessToken"] # Upload image through the proxy upload_res = requests.post(f"{FOURMEME_PROXY}/upload", json={ "accessToken": access_token, "image": image_data_url }) # Request transaction arguments through the proxy prepare_res = requests.post(f"{FOURMEME_PROXY}/prepare", json=prepare_body) prepare_data = prepare_res.json() if not prepare_data.get("success"): raise Exception(f"Prepare failed: {prepare_data}") create_arg = prepare_data["createArg"] signature = prepare_data["signature"] contract_address = prepare_data["contractAddress"] ``` ### Technical Analysis The recommended workflow sends a wallet login signature to `bapbook-api.fly.dev` and then relies on that intermediary to obtain and handle a Four.Meme access token. It also accepts the transaction arguments, API signature, and target contract address retur ...[truncated 2378 chars]
Remediation
## Remediation Suggestions - Make the official direct Four.Meme API workflow the default. - Do not forward wallet-authenticated session tokens through an unnecessary intermediary. - Explain the trust implications and obtain informed user consent before using any proxy. - Maintain an explicit allowlist of expected chain IDs and audited token-manager contract addresses. - Decode and display all transaction arguments, recipients, tax settings, and native value before signing. - Confirm that fee-recipient addresses match the user-approved wallet. - Simulate transactions locally through a trusted RPC endpoint and reject unexpected state changes. - Require explicit user confirmation when a returned contract address is new or differs from a previously approved address. - Apply timeouts, response-size limits, schema validation, and safe error handling to all external requests.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:132
Finding
Unpinned Runtime Installation of Security-Critical Dependencies## Vulnerability Details **File Location**: `SKILL.md`, line 132 **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash pip install eth-account web3 requests ``` ### Technical Analysis The Skill instructs users to install third-party packages without fixed versions, integrity hashes, a lockfile, or an isolated environment requirement. These packages participate directly in private-key handling, message signing, transaction construction, and network communication. Because dependency versions are unconstrained, the effective code executed by the Skill can change after review. A compromised future release, malicious dependency in the transitive graph, repository configuration error, or unexpected breaking update could run code with the user's installation privileges and access locally stored wallet credentials. No evidence was found that the named packages are themselves malicious. The confirmed issue is the unsafe dependency-resolution and installation practice. ### Attack Path 1. The user follows the setup instructions and runs the unpinned `pip install` command. 2. The package resolver selects the latest versions and their current transitive dependencies. 3. A compromised, malicious, or unexpectedly changed package executes installation or runtime code. 4. The package runs in the same environment as the Skill. 5. It reads `agent_wallet.json`, intercepts signatures, modifies transaction construction, or sends credentials to an external service. 6. The attacker uses the captured signing material to control the wallet or alter blockchain transactions. ### Impact Assessment A malicious dependency could obtain the same privileges as the user running the installation or Skill. It could read wallet private keys and mnemonics, alter destination addresses and transaction data, intercept API access tokens, execute local commands, or compromise other data acce ...[truncated 194 chars]
Remediation
## Remediation Suggestions - Pin every direct and transitive dependency to a reviewed version. - Supply cryptographic hashes and enforce them with `pip install --require-hashes`. - Maintain a reviewed lockfile or fully hashed requirements file. - Install dependencies in an isolated virtual environment with minimum filesystem privileges. - Use the canonical package index explicitly and prevent untrusted extra indexes. - Scan dependencies for known vulnerabilities and review updates before deployment. - Separate wallet-signing functionality into a constrained component so ordinary dependencies cannot read raw key material.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
SKILL.md:887
Finding
Unrestricted Autonomous Transaction Signing with Raw Private Keys and Arbitrary Calldata## Vulnerability Details **File Location**: `SKILL.md`, lines 887-905 **Additional Location**: `SKILL.md`, lines 945 and 982-985 **Vulnerability Type**: Excessive wallet privileges and unrestricted contract execution **Risk Level**: High ### Vulnerable Code ```bash ### set-key - Enable Autonomous Trading Set the agent's wallet private key to enable autonomous trading: # WARNING: This gives OpenClaw control of agent funds! bap578 set-key --agent 42 --key 0xPRIVATE_KEY ``` ```bash ### trade - Execute as Agent # Execute a swap as agent #42 bap578 trade --agent 42 \ --to 0x10ED43C718714eb63d5aA57B78B24704C8cF9845 \ --data 0x7ff36ab500000000000000000000000000000000000000000000000000000000 # The agent's wallet signs and executes this transaction ``` The Skill also instructs users to configure a treasury private key: ```bash bap578 config --treasury YOUR_WALLET_PRIVATE_KEY ``` ### Technical Analysis The documented interface gives the agent a raw wallet private key and permits transactions with arbitrary destination addresses and calldata. The instructions do not establish contract or function allowlists, per-transaction and cumulative spending limits, ABI decoding, transaction simulation, slippage bounds, approval controls, recipient validation, or mandatory human confirmation. Arbitrary calldata is not limited to token swaps. It can represent native-asset transfers, unlimited token approvals, ownership changes, calls to hostile contracts, or interactions with contracts that execute callbacks and reentrant behavior. This level of control exceeds the minimum privilege necessary for ordinary trading. A safer design can expose narrowly typed swap operations without granting unrestricted contract-call capability or persistent access to a raw private key. The referenced `bap578.py` implementation is not present in the audited project. Consequently, any safeguards that might exist in the implementati ...[truncated 1332 chars]
Remediation
## Remediation Suggestions - Replace raw `to` and `data` transaction interfaces with narrowly typed, validated operations. - Enforce audited contract, router, token, and function-selector allowlists. - Decode calldata locally and reject unknown or ambiguous functions. - Simulate every transaction and verify expected asset and state changes before signing. - Set per-transaction, daily, and cumulative spending limits. - Require explicit user confirmation for new contracts, approvals, ownership changes, and material-value transactions. - Reject unlimited token approvals and automatically revoke temporary approvals after use. - Enforce minimum received amounts, deadlines, price-impact limits, and slippage limits for swaps. - Keep treasury credentials separate from agent trading credentials. - Use a limited hot wallet or smart-account session key instead of a treasury or unrestricted private key. - Provide an emergency revocation mechanism and transaction audit log.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (22)

Missing User Warnings

Medium
Confidence
99% confidence
Finding
The sample code writes a private key and seed phrase to agent_wallet.json in plaintext on disk. Any local compromise, log exposure, backup leak, or multi-user host access would give an attacker full control over the wallet and any assets or identities tied to it.

External Transmission

Medium
Category
Data Exfiltration
Content
# ── Step 4a: Get nonce ──────────────────────────────────────────
# IMPORTANT: parameter name is "accountAddress" (NOT "address")
nonce_res = requests.post(f"{FOURMEME_PROXY}/nonce", json={
    "accountAddress": wallet["address"]
})
nonce_data = nonce_res.json()
Confidence
70% 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
message_hash = encode_defunct(text=message)
sig = account.sign_message(message_hash)

login_res = requests.post(f"{FOURMEME_PROXY}/login", json={
    "address": wallet["address"],
    "signature": sig.signature.hex()
})
Confidence
90% confidence
Finding
The login request sends the wallet address and an authentication signature to an external service. While signatures are intended for authentication, sending them to third parties without prominent trust and replay-scope guidance can enable account misuse within that service or user confusion about what is being authorized.

External Transmission

Medium
Category
Data Exfiltration
Content
mime = "image/png" if TOKEN_IMAGE_PATH.endswith(".png") else "image/jpeg"
    image_data_url = f"data:{mime};base64,{base64.b64encode(image_bytes).decode()}"

upload_res = requests.post(f"{FOURMEME_PROXY}/upload", json={
    "accessToken": access_token,
    "image": image_data_url
})
Confidence
91% confidence
Finding
This step uploads a base64-encoded image and access token to a remote proxy. That creates privacy and credential-handling risk, especially because the skill presents the proxy as recommended without substantive security disclosure or minimization guidance.

External Transmission

Medium
Category
Data Exfiltration
Content
"minSharing": 100000               # Min tokens to participate in dividends
}

prepare_res = requests.post(f"{FOURMEME_PROXY}/prepare", json=prepare_body)
prepare_data = prepare_res.json()
if not prepare_data.get("success"):
    raise Exception(f"Prepare failed: {prepare_data}")
Confidence
92% confidence
Finding
The token preparation request sends detailed token metadata and an access token to an external proxy. If the proxy is compromised or untrusted, it can observe launch plans and misuse the token, and the skill does not adequately frame that risk.

External Transmission

Medium
Category
Data Exfiltration
Content
# Note: Contract address is returned by the API based on tax settings

# Step 1: Get nonce for authentication
nonce_response = requests.post(f"{FOURMEME_API}/private/user/nonce/generate", json={
    "accountAddress": wallet["address"],
    "verifyType": "LOGIN",
    "networkCode": "BSC"
Confidence
70% 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
# Note: Contract address is returned by the API based on tax settings

# Step 1: Get nonce for authentication
nonce_response = requests.post(f"{FOURMEME_API}/private/user/nonce/generate", json={
    "accountAddress": wallet["address"],
    "verifyType": "LOGIN",
    "networkCode": "BSC"
Confidence
70% 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
message_hash = encode_defunct(text=message)
signature = account.sign_message(message_hash)

login_response = requests.post(f"{FOURMEME_API}/private/user/login/dex", json={
    "region": "WEB",
    "langType": "EN",
    "verifyInfo": {
Confidence
90% confidence
Finding
The login flow transmits a wallet-linked signature to a third-party API. That is security-sensitive because the signature authenticates the caller to the remote platform, and the skill does not clearly warn about trust, replay scope, or credential handling.

External Transmission

Medium
Category
Data Exfiltration
Content
#         mime_type = "image/png"
#     image_data_url = f"data:{mime_type};base64,{image_base64}"
# 
# upload_response = requests.post(
#     f"{BAPBOOK_API}/api/fourmeme/upload",
#     headers={"Content-Type": "application/json"},
#     json={"accessToken": access_token, "image": image_data_url}
Confidence
70% 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
}
}

create_response = requests.post(f"{FOURMEME_API}/private/token/create", 
    headers={"meme-web-access": access_token, "Content-Type": "application/json"},
    json=create_body
)
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The BapBook flow sends agent identity details and receives/uses an API key from a third-party service without clear disclosure of what data is transmitted or how the credential should be protected. This can lead to accidental credential leakage, unauthorized posting, or privacy surprises if operators treat the example as safe-by-default.

External Transmission

Medium
Category
Data Exfiltration
Content
BAPBOOK_API = "https://bapbook-api.fly.dev"

# Step 1: Register on BapBook
register_response = requests.post(f"{BAPBOOK_API}/api/webhook", json={
    "action": "register",
    "agent_name": "MyAutonomousAgent",
    "twitter_handle": "@myagent"
Confidence
94% confidence
Finding
Registration sends agent identity attributes to a remote webhook and returns API credentials, but the skill gives little warning about privacy, credential handling, or trust in the remote service. This can lead to accidental exposure of identifiers and misuse of issued credentials.

External Transmission

Medium
Category
Data Exfiltration
Content
print(f"Registered on BapBook! Agent ID: {agent_id}")

# Step 2: Post about your token launch!
post_response = requests.post(f"{BAPBOOK_API}/api/webhook", json={
    "action": "post",
    "agent_id": agent_id,
    "api_key": api_key,
Confidence
95% confidence
Finding
The posting request transmits an API key and content to a remote webhook. If the key is logged, intercepted, or mishandled, an attacker could impersonate the agent on that service and post unauthorized content.

External Transmission

Medium
Category
Data Exfiltration
Content
BNBSHARE_API = "https://bnbshare.fun/api/v2"

# Step 1: Upload metadata to IPFS
meta_response = requests.post(f"{BNBSHARE_API}/metadata", json={
    "image": "data:image/png;base64,...",  # Base64 encoded image
    "name": "Agent42 Coin",
    "description": "The official token of Agent #42"
Confidence
70% 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
metadata = meta_response.json()

# Step 2: Get transaction parameters
params_response = requests.post(f"{BNBSHARE_API}/token-params", json={
    "name": "Agent42 Coin",
    "symbol": "A42",
    "metadataCid": metadata["metadataCid"],
Confidence
70% 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
# - value: BNB amount in wei

# Step 4: Register token after tx confirms
register_response = requests.post(f"{BNBSHARE_API}/register-token", json={
    "txHash": "0x...",
    "name": "Agent42 Coin",
    "symbol": "A42",
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The section at L1245-L1249 says BAP-578 agents with a BapBook Passport can launch tokens on Four.Meme and lists a passport as a requirement. This directly contradicts the earlier operational guidance at L0022 and L0374, which explicitly says a passport is not needed for Four.Meme and that the service is independent.

External Transmission

Medium
Category
Data Exfiltration
Content
message = f"You are sign in Meme {nonce}"
signature = account.sign_message(message)

login_response = requests.post(f"{FOURMEME_API}/private/user/login/dex", json={
    "region": "WEB",
    "langType": "EN",
    "verifyInfo": {
Confidence
90% confidence
Finding
This login example sends a signature to authenticate with an external service, which is security-sensitive even if common in Web3 workflows. Without explicit trust and scope warnings, operators may not appreciate that the signature grants off-chain account access on that platform.

External Transmission

Medium
Category
Data Exfiltration
Content
# Step 4: Prepare token creation with TAX TOKEN enabled
# For self-tokenization, default is 1% tax with 100% going to agent wallet
create_response = requests.post(f"{FOURMEME_API}/private/token/create", 
    headers={"meme-web-access": access_token},
    json={
        "name": "Agent42 Coin",
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The documentation repeatedly warns that token creation should use gas estimation and not hardcoded gas limits, including explicit troubleshooting guidance at L0030-L0033 and implementation examples at L0501-L0516/L0712-L0724. However, the later example at L1353-L1360 builds the transaction with a fixed gas value of 500000, contradicting that stated intent and recommended behavior.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The Four.Meme login example explicitly sets `"langType": "EN"`, which forces a language choice in the workflow. The file does not provide any user opt-in or explain why English is required, so this is a natural-language locale policy issue.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
This later token-launch example also sets `"langType": "EN"` in the login request. Repeating a fixed English locale without offering a choice or justification violates the same language/locale policy expectation.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
SKILL.md:581