Back to skill

Security audit

HumanNFT

Security checks for vulnerabilities and agentic risk

Overview

This skill is for real-money NFT trading and is coherent, but it gives agents broad wallet-enabled authority with weak safeguards.

Install only if you are comfortable giving this workflow access to a HumanNFT API key and a wallet able to transact on Base mainnet. Use a dedicated low-balance wallet, require explicit approval for every signature and transaction, verify transaction recipient, chain ID, value, token ID, and calldata before signing, and avoid running the unpinned MCP package unless you have pinned and inspected the version.

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

T08 · Insecure Dependencies

Warning
Location
SKILL.md:103
Finding
Unpinned Third-Party Package Is Downloaded and Executed## Vulnerability Details **File Location**: `SKILL.md`, lines 103–109 **Vulnerability Type**: Unsafe execution of an unpinned third-party dependency **Risk Level**: Medium ### Vulnerable Code ```markdown ## MCP Server If your platform supports MCP, use the npm package (21 tools): ``` npx humannft-mcp ``` ``` ### Technical Analysis The Skill recommends invoking `npx humannft-mcp` without specifying a package version, integrity hash, lockfile, verified source repository, or trusted publisher identity. Depending on the local npm configuration, `npx` can download the currently published package and immediately execute its code. The effective code therefore may differ from the code available when this Skill was audited. The package is expected to receive `HUMANNFT_API_KEY` through its environment and may inherit additional process privileges, environment variables, filesystem access, and network access from the invoking agent. This behavior is relevant to the Skill's MCP integration, but unrestricted execution of the latest package version exceeds the minimum privilege necessary to communicate with the marketplace. ### Attack Path 1. An attacker compromises the npm package, its publisher account, or its release process. 2. The attacker publishes a malicious version under the existing package name. 3. A user or agent follows the Skill instructions and runs `npx humannft-mcp`. 4. `npx` downloads and executes the malicious release. 5. The package reads `HUMANNFT_API_KEY` or other accessible environment and host data. 6. The package transmits the collected information or performs unauthorized local actions using the inherited process privileges. ### Impact Assessment Successful exploitation could expose the HumanNFT API credential and any other information available to the process. Depending on the execution environment, malicious package code could read or modify accessible files, make arbitrary network request ...[truncated 287 chars]
Remediation
## Remediation Suggestions - Pin the package to a specific, audited version rather than resolving the latest release. - Use a lockfile and verify the package's integrity hash before installation or execution. - Document the authoritative package publisher, source repository, and expected release-signing or provenance information. - Install and inspect the pinned package before executing it; avoid automatic download-and-run behavior. - Run the MCP server in a sandbox with a read-only or narrowly scoped filesystem. - Expose only `HUMANNFT_API_KEY` and the minimum required environment variables to the process. - Restrict outbound network access to the documented HumanNFT API origin where operationally possible. - Rotate the API key immediately if an untrusted package version may have accessed it.

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:52
Finding
Server-Provided Blockchain Transactions Are Broadcast Without Independent Validation## Vulnerability Details **File Location**: `SKILL.md`, lines 52–58 **Related Locations**: `SKILL.md`, lines 76–99 and 142–144 **Vulnerability Type**: Blind signing and broadcasting of remote transaction data **Risk Level**: High ### Vulnerable Code ```markdown ## Critical Pattern — Every On-Chain Action ``` 1. POST to API → get "transaction" object 2. wallet.sendTransaction(transaction) → get txHash 3. POST to /confirm endpoint with txHash → updates the database ``` **NEVER skip step 3.** The UI reads from the database, not the blockchain. ``` The transaction-producing operations include: ```markdown ### Mint (auth required) ``` POST /api/mint → { transaction: { to, data, value, chainId } } POST /api/mint/confirm → { humanId, txHash, tokenId } ``` ### Marketplace (auth required) ``` POST /api/marketplace/list → { tokenId, priceEth } → transaction POST /api/marketplace/list/confirm → { tokenId, txHash, priceEth } POST /api/marketplace/buy → { tokenId } → transaction POST /api/marketplace/buy/confirm → { tokenId, txHash } POST /api/marketplace/cancel → { tokenId } → transaction POST /api/marketplace/cancel/confirm → { tokenId, txHash } POST /api/marketplace/update-price → { tokenId, newPriceEth } → 2 transactions (cancel + relist) ``` ``` The Skill additionally states: ```markdown - **NEVER** call smart contracts directly — always use the API. ``` ### Technical Analysis The documented workflow delegates construction of the complete blockchain transaction—including `to`, `data`, `value`, and `chainId`—to a remote API and then passes that object directly to `wallet.sendTransaction`. The instructions do not require the agent to decode or independently verify the returned transaction before signing it. A transaction must be checked against the user's actual request. Necessary checks include the expected chain ID, an allowlisted contrac ...[truncated 2019 chars]
Remediation
## Remediation Suggestions - Require explicit, informed user approval before every transaction that spends ETH, transfers an NFT, changes a listing, or creates an approval. - Verify that `chainId` is exactly the expected Base mainnet chain ID (`8453`). - Maintain an independently sourced allowlist of expected contract addresses; do not derive the allowlist from the same API response. - Decode calldata locally and verify the function selector and every argument against the user's request. - Check the transaction recipient, token ID, destination address, ETH value, listing price, and approval scope. - Reject unlimited or unrelated approvals unless they are explicitly required and separately authorized. - Enforce configurable per-transaction and cumulative spending limits. - Simulate transactions and inspect expected balance, ownership, approval, and state changes before signing. - Display human-readable transaction details and any simulation warnings to the user. - Fail closed when transaction decoding, contract identification, simulation, or state verification is unavailable. - Use a dedicated low-balance marketplace wallet to limit the consequences of API compromise.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:28
Finding
Wallet Registration Uses a Deterministic Replayable Signature## Vulnerability Details **File Location**: `SKILL.md`, lines 28–38 **Vulnerability Type**: Missing nonce, expiration, and domain binding in wallet authentication **Risk Level**: Medium ### Vulnerable Code ```javascript // Sign a message to prove wallet ownership const message = "Register on HumanNFT: " + wallet.address.toLowerCase(); const signature = await wallet.signMessage(message); const res = await fetch("https://humannft.ai/api/agents/register", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: "YOUR_AGENT", walletAddress: wallet.address, message, signature }) }); const { apiKey } = await res.json(); // SAVE apiKey — shown only once! ``` ### Technical Analysis The signed registration message is deterministic and contains only a fixed string and the wallet address. It contains no unpredictable server-issued nonce, expiration time, issuance time, chain ID, request identifier, or explicit origin binding. As a result, the same signature remains valid indefinitely if the server accepts repeated submissions. TLS protects the signature in transit when correctly implemented, but it does not prevent replay if the signature is exposed through application logs, browser instrumentation, compromised dependencies, endpoint compromise, debugging output, or another component with access to the request. Sending a wallet address and a proof-of-ownership signature to the declared registration service is necessary for the advertised registration function. The issue is not the network transmission itself; it is that the transmitted proof is reusable and insufficiently bound to one registration request and one authentication context. ### Attack Path 1. A user signs the deterministic registration message. 2. An attacker obtains the message and signature from logs, a compromised client component, request inspection, or another source with access to the registration payload. ...[truncated 1081 chars]
Remediation
## Remediation Suggestions - Replace the deterministic message with a server-generated, cryptographically random, single-use nonce. - Prefer Sign-In with Ethereum (EIP-4361) or an equivalent structured authentication standard. - Bind the signed statement to the intended domain and URI. - Include the chain ID, wallet address, issued-at timestamp, expiration time, nonce, and a clear registration purpose. - Store nonce state server-side and invalidate each nonce immediately after successful use. - Apply a short expiration window and reject expired, previously consumed, or context-mismatched messages. - Prevent an existing wallet registration from being rebound or overwritten without fresh proof and appropriate account controls. - Avoid logging signatures, API keys, or complete registration request bodies. - Rate-limit registration attempts and record security events for repeated or replayed proofs. - Return API credentials only after all nonce, domain, signature, and account-binding checks succeed.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Missing User Warnings

High
Confidence
97% confidence
Finding
The skill describes real-money on-chain trading on Base mainnet, including minting, buying, selling, and transferring NFTs, but it does not present a clear upfront warning that these actions spend real ETH and can cause irreversible financial loss. This is especially dangerous because the surrounding text encourages autonomous investing and operational use of wallet signing and transaction broadcasting.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger description includes broad activation terms such as any human NFT trading task, which can cause the skill to activate in loosely related contexts. Because this skill can lead to wallet signing, on-chain transactions, and financial actions, overbroad activation increases the chance of unintended invocation and unsafe autonomous behavior.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The usage guidance says the agent should be used when it wants to invest autonomously and for any task involving the marketplace, which is ambiguous and overly permissive. In context, this is risky because it normalizes autonomous financial decision-making and may trigger real-money blockchain actions without sufficiently specific user authorization.

External Transmission

Medium
Category
Data Exfiltration
Content
const message = "Register on HumanNFT: " + wallet.address.toLowerCase();
const signature = await wallet.signMessage(message);

const res = await fetch("https://humannft.ai/api/agents/register", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "YOUR_AGENT", walletAddress: wallet.address, message, signature })
Confidence
90% confidence
Finding
The registration flow transmits the agent name, wallet address, signed message, and resulting API key exchange to an external service. While this is functionally necessary for the marketplace, it is still a security-relevant data transmission because it couples identity, wallet proof, and credential issuance to a third-party endpoint; if mishandled, users could expose sensitive operational metadata or be registered with an untrusted service.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding
The skill instructs users to execute an unpinned MCP package via `npx humannft-mcp`, which fetches and runs the latest published code at execution time. In a wallet-enabled, real-money trading skill, this creates a supply-chain execution risk: a compromised or malicious package update could gain access to API keys, influence transaction generation, or exfiltrate sensitive data.

Static analysis

No suspicious patterns detected.