Back to skill

Security audit

Is Token Safe?

Security checks for vulnerabilities and agentic risk

Overview

The skill is not malicious, but its advertised token-safety check is unreliable and may give users or bots a false sense of safety.

Review carefully before installing or using in any automated trading flow. The artifacts do not show credential theft, persistence, or destructive behavior, but the skill can fail open or understate token risk, so it should not be trusted to decide whether a token is safe without fixes and tests.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scan.js.js:92
Finding
Confirmed Honeypot Risk Is Incorrectly Downgraded<![CDATA[ ## Vulnerability Details **File Location**: `scan.js.js`, lines 92-97 **Vulnerability Type**: Risk severity overwrite caused by non-monotonic decision logic **Risk Level**: High ### Complete Code Snippet ```js let risk = "LOW"; if (honeypot === true) risk = "HIGH"; if (blacklist_capable) risk = "MEDIUM"; if (mintable && !owner_renounced) risk = "MEDIUM"; ``` ### Technical Analysis The risk checks are independent assignments rather than severity-preserving decisions. Although a positive honeypot result initially sets `risk` to `HIGH`, either subsequent condition can overwrite it with `MEDIUM`. This behavior is especially likely because the implementation's blacklist and mint capability checks inspect the manually supplied local ABI rather than the deployed contract. Those checks therefore tend to produce positive values and trigger the downgrade. A confirmed honeypot is a stronger warning than minting or blacklist capability and must never be reduced by later, lower-severity findings. ### Attack Path 1. An attacker deploys or promotes a token that prevents or severely restricts token sales. 2. A user or automated trading agent scans the token. 3. The external honeypot service returns `isHoneypot: true`. 4. The code temporarily assigns `HIGH`. 5. A later blacklist or mint condition assigns `MEDIUM`. 6. The consumer receives an understated risk classification and may proceed with the trade. ### Impact Assessment An attacker does not obtain local system privileges through this flaw. However, the attacker may influence a security-sensitive trading decision by having a confirmed honeypot represented as only medium risk. The scope includes any bot, agent, or user relying on the scanner's `risk` field. Potential consequences include purchasing an asset that cannot be resold and loss of the funds used in the trade. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions Use severity-preserving logic so lower-priority findings cannot overwrite a higher-priority result. For example: ```js let risk = "LOW"; if (honeypot === true) { risk = "HIGH"; } else if (blacklist_capable || (mintable && owner_renounced === false)) { risk = "MEDIUM"; } ``` Alternatively, assign numeric severity scores and retain the maximum severity. Treat unavailable honeypot results separately as `UNKNOWN` rather than implicitly safe. Add regression tests covering combinations such as: - Honeypot only - Honeypot plus blacklist capability - Honeypot plus mint capability - Unknown owner status - Failed external API request Every case with `honeypot === true` must produce `HIGH`. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scan.js.js:18
Finding
Contract Capabilities Are Falsely Inferred from a Locally Defined ABI<![CDATA[ ## Vulnerability Details **File Location**: `scan.js.js`, lines 18-24 and 43-68 **Vulnerability Type**: Incorrect smart-contract capability detection **Risk Level**: Medium ### Complete Code Snippet ```js const abi = [ "function owner() view returns (address)", "function mint(address,uint256)", "function isBlacklisted(address) view returns (bool)", "function blacklist(address,bool)", "function setBlacklist(address,bool)" ]; const contract = new ethers.Contract(token, abi, provider); /* ========================= 2️⃣ mint 가능 여부 ========================= */ let mintable = false; try { contract.interface.getFunction("mint"); mintable = true; } catch { mintable = false; } /* ========================= 3️⃣ blacklist 기능 여부 ========================= */ let blacklist_capable = false; try { contract.interface.getFunction("blacklist"); blacklist_capable = true; } catch { try { contract.interface.getFunction("setBlacklist"); blacklist_capable = true; } catch { blacklist_capable = false; } } ``` ### Technical Analysis `contract.interface.getFunction()` searches the `ethers` interface created from the local ABI. It does not inspect deployed bytecode, query a verified contract ABI, or prove that the target address implements the selected function. Because `mint`, `blacklist`, and `setBlacklist` are explicitly included in the local ABI, the lookups succeed independently of the target contract's actual functionality. Consequently: - `mintable` is reported as `true` for arbitrary targets. - `blacklist_capable` is reported as `true` because `blacklist` is present in the local interface. - The risk calculation is based on fabricated capability information. - The false blacklist result contributes to downgrading confirmed honeypots from `HIGH` to `MEDIUM`. Even an RPC call to an assumed selector would require careful interpretation: reverts do not always prove absence, and successful calls do not necessarily establish t ...[truncated 1024 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Replace local-interface introspection with evidence obtained from the deployed contract: 1. Validate the address with `ethers.isAddress()` and normalize it with `ethers.getAddress()`. 2. Confirm that `provider.getCode(address)` returns deployed bytecode rather than `0x`. 3. Retrieve and validate a verified ABI from a trusted chain explorer when available. 4. For unverified contracts, analyze runtime bytecode for selectors while clearly treating selector presence as heuristic evidence, not proof of functionality. 5. Resolve proxy implementations before analyzing capabilities. 6. Assess access controls and actual callable behavior, including whether minting is restricted or ownership has genuinely been renounced. 7. Represent uncertain results explicitly as `unknown`, rather than `true` or `false`. 8. Add tests against contracts that do and do not implement each capability. Do not use `contract.interface.getFunction()` as evidence that a deployed target implements a function when the same application supplied that interface. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
skill.json.txt:5
Finding
Configured Skill Entry Point Is Missing and the Available Handler Performs No Safety Scan<![CDATA[ ## Vulnerability Details **File Location**: `skill.json.txt`, line 5; `index.js.js`, lines 1-6 **Vulnerability Type**: Entry-point and implementation mismatch **Risk Level**: Medium ### Complete Code Snippets Configured entry: ```json { "name": "is_token_safe", "version": "0.1.0", "description": "Quick token safety check for bots", "entry": "index.js" } ``` Available handler: ```js module.exports = async function (input) { return { ok: true, input }; }; ``` ### Technical Analysis The configuration declares `index.js`, but the project contains `index.js.js`. Therefore, a runtime following the metadata may be unable to resolve the entry point. If the available `index.js.js` handler is invoked by an alternative loader, it only echoes the supplied input and returns `ok: true`. It does not: - Validate a token address. - Invoke the scanner. - Query contract or honeypot information. - Return the documented low, medium, or high risk level. - Return the documented reason summary. This creates a fail-open interface: a successful-looking response can be produced despite no security analysis having taken place. ### Attack Path 1. A bot or agent installs the skill based on its token-safety description. 2. The runtime attempts to load the declared `index.js` and fails because that file is absent; alternatively, it resolves `index.js.js`. 3. If the echo handler runs, attacker-controlled or arbitrary input is returned with `ok: true`. 4. No token analysis occurs. 5. A consumer that interprets successful execution as successful validation may continue with an unsafe token. ### Impact Assessment The flaw does not directly provide filesystem, process, wallet, or network privileges to an attacker. It compromises the availability and integrity of the advertised security function. The affected scope includes every caller using the configured skill entry. Depending on caller behavior, the result may be a loading failure or a false impression ...[truncated 40 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Rename the implementation to `index.js` or update the metadata to the exact real filename supported by the runtime. 2. Export the scanner through the configured entry module rather than keeping it only as a standalone CLI. 3. Validate input with `ethers.isAddress()` instead of checking length alone. 4. Return a stable documented schema containing the token, risk level, reason summary, evidence, and an explicit status for unavailable checks. 5. Do not use `ok: true` to imply that a token is safe; distinguish successful execution from a favorable security result. 6. Fail closed or return `risk: "UNKNOWN"` when required analysis cannot be performed. 7. Add integration tests that load the entry declared in the metadata and verify that real analysis is executed. 8. Keep the CLI wrapper separate from reusable scanning logic so both interfaces invoke the same audited implementation. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (1)

External Transmission

Medium
Category
Data Exfiltration
Content
try {
    const res = await axios.get(
      `https://api.honeypot.is/v2/IsHoneypot`,
      {
        params: {
          address: token,
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.