T01 · Skill Instruction Hijacking
- Location
SKILL.md:23- Finding
Forced Branded Output Injection Through Skill Instructions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its wallet-balance purpose, but it stores wallet addresses in a shared unauthenticated service that could expose or alter saved addresses if the gateway is reachable.
Review before installing, especially if the gateway could be exposed beyond your machine. Only save wallet addresses you are comfortable storing in a shared local file, keep the service bound to localhost or behind authentication, and expect queried addresses to be sent to Antalpha MCP and public blockchain/price providers.
SKILL.md:23Forced Branded Output Injection Through Skill Instructions
server.js:996Unauthenticated Disclosure and Modification of Persistent Wallet Memory
server.js:307Rate Limiting Can Be Bypassed Through Spoofed Proxy Headers or Redis Failure
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
cp .env.example .env
npm install
npm start
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
cp .env.example .env
npm install
npm start
ws is a real-time networking library handling untrusted remote input, and the cited issues include memory disclosure and memory exhaustion. Even if WebSocket support is only transitively present through ethers, shipping a vulnerable version increases risk if any code path enables WebSocket RPC/providers, and in a wallet service this can expose sensitive process memory or cause service instability.
The README states that wallet queries use external MCP and public providers but does not warn users that submitted wallet addresses will be transmitted to third-party services. Wallet addresses are sensitive financial identifiers, and sending them to external services without an explicit privacy warning can expose user activity and balance lookups beyond the local environment.
The README advertises address memory but does not clearly warn that wallet addresses are stored persistently and can later be queried automatically. For a wallet-related skill, persisted address history is sensitive metadata that can reveal financial relationships or holdings, so omission of a retention/privacy notice increases the risk of users unknowingly exposing their data.
The example phrases include very broad triggers such as "What's in my wallet?" and "查我的余额", which can plausibly appear in normal conversation and may cause the skill to activate unexpectedly. In this skill, unexpected activation is more sensitive because it can query remembered wallet addresses and send them to external providers, creating privacy and data-minimization risks.
The skill performs network operations and may access environment-backed runtime capabilities, but it declares no explicit tool scope or permissions boundary. That weakens reviewability and policy enforcement, making it easier for the skill to gain or retain broader execution capabilities than users or operators expect.
The remembered-address trigger is broad enough that ordinary phrases like 'check my balance' can activate queries against previously stored wallet addresses without fresh confirmation. This can cause unintended use of persisted sensitive financial identifiers and may surprise users who did not realize memory would be consulted.
The fallback behavior sends user-supplied wallet addresses to a public remote endpoint outside the local gateway path. This broadens data exposure to a third party and may leak sensitive financial interest or address-linkage metadata, especially because users may expect balance checks to remain within company-controlled infrastructure.
curl -sS --connect-timeout 5 --max-time 90 --retry 1 \
"https://api.antalpha.com/agent-skills/v1/assets?input={{input}}" \
-H "Accept: application/json"
The skill asks to remember wallet addresses and supports persistent retrieval, but it does not clearly warn that the address will be stored and reused later. Wallet addresses are sensitive financial metadata; persistent storage without explicit privacy notice and retention expectations can expose user activity patterns or link identities across sessions.
The skill transmits the full canonical wallet address to a memory API for persistence. Even though the endpoint is local, this is still an external transmission of sensitive user financial identifiers, and compromise or logging at that service boundary could expose wallet ownership correlations.
When the user clearly wants to save (e.g. "remember", "yes", "记住", "是", "save this address"), call with the full canonical address from the query you just ran:
curl -sS --connect-timeout 5 --max-time 15 -X POST \
"http://127.0.0.1:3000/agent-skills/v1/memory" \
-H "Content-Type: application/json" \
-d '{"add":"{{full canonical address or original input}}"}'
The manifest describes the skill as handling 'Multi-chain wallet balances (EVM + BTC)' with non-BTC addresses using the MCP wallet-balance-query tool, which implies an EVM-plus-BTC scope. However, the code explicitly detects and processes many additional non-EVM chains such as Tron, TON, XRP, Litecoin, NEAR, Sui, Aptos, Polkadot, Cardano, Kaspa, and Solana, expanding the supported asset-query scope beyond what the description claims.
The skill sends user-supplied wallet addresses to external services such as the MCP endpoint and public blockchain/RPC providers. Even if needed for functionality, transmitting wallet identifiers without clear disclosure or consent creates a privacy issue because third parties can correlate addresses, timing, and source metadata.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
}
async function fetchCoinPriceUsd(ids, signal) {
const url = `https://api.coingecko.com/api/v3/simple/price?ids=${encodeURIComponent(ids.join(","))}&vs_currencies=usd`;
const resp = await fetch(url, {
method: "GET",
headers: { Accept: "application/json" },
The service persistently stores wallet addresses in a local file and exposes read/write memory endpoints, but there is no authentication, per-user isolation, consent tracking, or deletion policy. Wallet addresses are sensitive financial identifiers, so storing them globally can leak one user's remembered addresses to another caller and create privacy risk.
The manifest describes a skill focused on querying wallet balances and remembering addresses, but this lockfile shows first-party dependencies on Express and Redis in addition to chain-query libraries. While Redis may support the stated 'remembering addresses' feature, Express indicates a general HTTP server capability that is not part of the user-facing skill purpose as described in the manifest and expands the skill's operational surface beyond simple balance retrieval.
body-parser processes attacker-controlled HTTP request bodies, so a denial-of-service flaw in this dependency can be reachable in an Express-based service. In this wallet-balance skill, availability matters because the package set indicates a network-facing gateway, but the issue appears limited to service disruption rather than code execution or data compromise.
qs is commonly used to parse or serialize query strings from untrusted input, and the listed advisories are denial-of-service class issues. Because this skill likely exposes HTTP query endpoints for address lookups, malformed attacker-supplied parameters could potentially consume resources or crash request handling, though the impact is still primarily availability-related.
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.
"author": "Antalpha",
"license": "MIT",
"dependencies": {
"decimal.js": "^10.5.0",
"dotenv": "^17.3.1",
"ethers": "^6.13.2",
"express": "^4.21.2",
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.
"license": "MIT",
"dependencies": {
"decimal.js": "^10.5.0",
"dotenv": "^17.3.1",
"ethers": "^6.13.2",
"express": "^4.21.2",
"helmet": "^8.1.0",
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.
"dependencies": {
"decimal.js": "^10.5.0",
"dotenv": "^17.3.1",
"ethers": "^6.13.2",
"express": "^4.21.2",
"helmet": "^8.1.0",
"redis": "^4.7.0"
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.
"decimal.js": "^10.5.0",
"dotenv": "^17.3.1",
"ethers": "^6.13.2",
"express": "^4.21.2",
"helmet": "^8.1.0",
"redis": "^4.7.0"
}
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.
"dotenv": "^17.3.1",
"ethers": "^6.13.2",
"express": "^4.21.2",
"helmet": "^8.1.0",
"redis": "^4.7.0"
}
}
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.
"ethers": "^6.13.2",
"express": "^4.21.2",
"helmet": "^8.1.0",
"redis": "^4.7.0"
}
}
The manifest repeatedly frames the feature around wallet addresses and remembering addresses, but the code also accepts ENS and .bnb domain names and resolves them to on-chain addresses. This is extra user-facing behavior not reflected in the declared description, creating a smaller but real description-to-behavior mismatch.
Detected: suspicious.env_credential_access