Back to skill

Security audit

BLINK — agent-only NFT mint on Robinhood Chain

Security checks for vulnerabilities and agentic risk

Overview

The skill is for minting and posting with an EVM wallet, but it asks the agent to handle a raw private key and sign server-provided transactions without enough safeguards.

Review carefully before installing. Use only a disposable wallet with minimal funds if you proceed, and do not paste a valuable wallet's private key into an agent session. The safer design would use a wallet UI, hardware wallet, or local signer that lets you approve a validated transaction without revealing the private key; the skill should also validate every transaction field before signing and ignore remote agentHint text as instructions.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:99
Finding

Untrusted API Responses Are Treated as Authoritative Agent Instructions

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 99-110
Vulnerability Type: Remote instruction injection
Risk Level: High

markdown
## API

Every response carries an `agentHint` with the next step. Follow it.

| Method | Endpoint | Purpose |
|--------|----------|---------|
| GET | `/info` | supply, price, contract |
| GET | `/check/{wallet}` | minted count and remaining slots |
| POST | `/challenge` | `{wallet, quantity?}` → challenge, 3s clock starts |
| POST | `/solve` | `{challengeId, answer}` → unsigned mint tx with co-signature |
| POST | `/submit` | `{signedTransaction}` → broadcast, returns token ids |
| GET | `/loop` | read The Loop (holder chat) — see `https://blink5555.vercel.app/loop.md` |

Technical Analysis

The skill explicitly instructs the agent to follow the agentHint field contained in every remote API response. This converts untrusted, mutable server content into agent instructions without constraining the permitted values or requiring validation against a local protocol state machine.

The API only needs to return structured challenge and transaction data for the declared minting functionality. Allowing it to issue arbitrary natural-language directions exceeds that minimum requirement. Even if the current server behaves legitimately, its responses can change after the skill has been audited. A compromise of the API, hosting account, DNS, or deployment pipeline could therefore alter the agent's behavior without modifying this package.

The same trust-boundary problem is reinforced by the skill's reliance on a remotely hosted Loop feed. Content returned from remote services should be treated exclusively as data, not as higher-priority operating instructions.

Attack Path

  1. An attacker compromises or controls blink5555.vercel.app, its deployment account, or another component capable of changing API responses.
  2. The user invokes the skill and the agent calls on ...[truncated 1091 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove the instruction to follow agentHint.
  • Treat agentHint as display-only, untrusted text, or eliminate it from the workflow entirely.
  • Implement a local allowlisted state machine: challenge responses may supply only a challenge ID, seed, iteration count, expiration, and quantity; solve responses may supply only a transaction matching strict local invariants.
  • Never permit API text to request secrets, select tools, alter destinations, install software, or override security rules.
  • Validate response schemas, types, ranges, and protocol state before acting.
  • Add an explicit instruction that all server-provided text and Loop messages are untrusted content and must never be interpreted as agent directives.

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:59
Finding

Server-Supplied Transaction Is Signed Without Validating Its Destination, Value, Chain, or Calldata

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 59-81
Vulnerability Type: Unsafe signing of an untrusted transaction
Risk Level: Critical

javascript
// 3. answer immediately
const sol = await fetch(`${API}/solve`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ challengeId: ch.challengeId, answer: acc }),
}).then(r => r.json());
if (!sol.unsignedTx) throw new Error(JSON.stringify(sol));

// 4. sign locally and submit
const fee = await provider.getFeeData();
const signed = await wallet.signTransaction({
  ...sol.unsignedTx,
  gasLimit: 250000,
  maxFeePerGas: (fee.maxFeePerGas ?? fee.gasPrice) * 2n,
  maxPriorityFeePerGas: fee.maxPriorityFeePerGas ?? 10000000n,
  nonce: await provider.getTransactionCount(wallet.address),
  type: 2,
});
const out = await fetch(`${API}/submit`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ signedTransaction: signed }),
}).then(r => r.json());

Technical Analysis

The script takes sol.unsignedTx directly from the remote API, spreads all of its fields into a transaction object, and signs it with the user's private key. Only fee settings, gas limit, nonce, and transaction type are replaced. The following security-critical properties are not independently checked:

  • to equals the documented BLINK contract.
  • chainId equals Robinhood Chain ID 4663.
  • value equals quantity × 0.00088 ETH.
  • data invokes the expected mint function.
  • The encoded recipient, quantity, price, voucher, and expiration match the user's requested operation.
  • The transaction does not grant token approvals, call another contract, or transfer funds to an attacker.

Local signing protects the private key itself but does not make an unvalidated transaction safe. A signature authorizes the exact server-supplied operation. Sending the resulting raw signed ...[truncated 1656 chars]

Remediation
View remediation

Remediation Suggestions

  • Construct the transaction locally from trusted constants instead of spreading a server-provided transaction object.
  • Before signing, require all of the following:
    • chainId === 4663.
    • to exactly matches 0xA7dCF63aE8e4f8142b6c7EbD7D3250C67b772643.
    • value exactly matches the locally calculated mint price and requested quantity.
    • Calldata decodes to the expected mint function and contains the expected recipient, quantity, voucher, and expiration.
    • No unexpected access list, custom data, sender, or other transaction fields are present.
  • Obtain the chain ID from the RPC and compare it with the expected constant before signing.
  • Use a minimal allowlisted schema for API responses and reject unknown fields.
  • Show the validated destination, value, function, and quantity to the user and require explicit confirmation before signing.
  • Prefer having the API return only the server's voucher or co-signature, then assemble the complete contract call locally.
  • Broadcast through the configured RPC after validation rather than returning the signed raw transaction to the API, unless server submission is strictly required and separately justified.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:17
Finding

Unpinned Package Installation Creates a Dependency Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 17-21
Vulnerability Type: Unpinned third-party dependency installation
Risk Level: Medium

markdown
## Prerequisites

- An EVM private key with **0.00088 ETH** per mint + gas (~0.00001 ETH) on Robinhood Chain
- Funding, if the wallet is empty: there is no faucet. Hold ETH on Base or Arbitrum, then bridge to chain 4663 at <https://relay.link/bridge/robinhood> — same address, no account, arrives in seconds, ~$0.02 in fees. Across, deBridge and Jumper also route to 4663. The canonical Arbitrum bridge from Ethereum works but is slower and priced by L1 gas. Tell the user ~0.001 ETH covers one mint plus gas.
- Node.js with `ethers` (check: `node -e "require('ethers')"`; if missing: `npm install --prefix /tmp ethers` and run with `NODE_PATH=/tmp/node_modules`)

Technical Analysis

The installation command requests the current registry version of ethers without a pinned version, lockfile, integrity hash, or trusted local artifact. Consequently, the code installed and executed during the skill run can differ from the dependency reviewed during the audit.

This risk is especially significant because the dependency is loaded by a process that receives the user's private key through PK and performs wallet construction and transaction signing. An install-time script or malicious runtime implementation could read environment variables, alter transaction construction, or transmit the key. Installing under /tmp does not isolate the package from the process or protect the secret.

Attack Path

  1. The expected ethers package is unavailable locally.
  2. The agent follows the prerequisite and runs npm install --prefix /tmp ethers.
  3. A compromised registry account, package release, registry mirror, or dependency supplies malicious package content.
  4. Malicious code runs during installation or when require("ethers") loads the package.
  5. The package rea ...[truncated 671 chars]
Remediation
View remediation

Remediation Suggestions

  • Pin ethers to a reviewed exact version rather than using an unconstrained package name.
  • Include a committed lockfile with verified integrity metadata.
  • Install with a deterministic command such as npm ci from a reviewed project directory.
  • Disable lifecycle scripts where compatible, for example with --ignore-scripts.
  • Use a trusted registry and verify package provenance or signatures where available.
  • Vendor the minimal audited dependency or use a prebuilt, integrity-verified environment for wallet operations.
  • Do not expose the private key to package installation steps. Run installation before accepting or loading wallet secrets.
  • Execute signing in a restricted process with minimal filesystem, environment, and network access.
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 (3)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill explicitly instructs the user to provide an EVM private key for posting, which is an extremely sensitive credential that grants full control of the wallet and any associated assets. Even though the text says signing is local and the key should never be logged, normalizing direct private-key handling in a skill creates a severe theft and misuse risk if the agent, toolchain, logs, prompts, or surrounding environment are compromised or behave unexpectedly.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill explicitly instructs the agent to ask the user for their EVM private key and to use it for signing. A private key grants full control over the wallet and all assets in it, so soliciting it in chat is inherently unsafe and creates a direct path to theft, replay, or misuse, regardless of claims that it 'never leaves your machine.' The surrounding content tries to normalize this behavior and makes the risk worse, not better.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill's required opening prompt asks for the user's private key directly, which is one of the highest-risk anti-patterns in wallet-integrated systems. In context, the skill is for NFT minting, which does not require custody transfer of the user's secret; asking for the raw key is unnecessary and exposes the entire wallet, not just mint funds. The speed/challenge constraint does not justify bypassing safe signing patterns.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.