Back to skill

Security audit

Quick Intel Token Security Scanner

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate paid token-scanning skill, but it gives agents broad permission to trigger paid wallet-backed scans and includes payment-signing examples that under-validate what the wallet signs.

Install only if you are comfortable sending token addresses and chains to Quick Intel and using an x402 payment wallet. Prefer a managed wallet or a dedicated low-balance wallet, never a main wallet key, and require the agent to show the cost and ask before each scan. If using the manual signing examples, add strict checks for expected amount, token contract, recipient, chain, and EIP-712 domain before signing.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:158
Finding
Unvalidated Server-Controlled Payment Authorization## Vulnerability Details **File Location**: `SKILL.md:158-179, 190-199`; duplicated in `Reference.md:174-195, 203-212` and the ethers.js flow at `Reference.md:254-276, 285-294` **Vulnerability Type**: Unvalidated payment parameters from an external service **Risk Level**: High ### Vulnerable Code ```javascript // Step 2: Find preferred network in accepts array const networkInfo = paymentRequired.accepts.find(a => a.network === 'eip155:8453'); if (!networkInfo) throw new Error('Base network not available'); // Step 3: Sign EIP-712 TransferWithAuthorization const nonce = keccak256(toHex(`${Date.now()}-${Math.random()}`)); const validBefore = BigInt(Math.floor(Date.now() / 1000) + 3600); const signature = await account.signTypedData({ domain: { name: networkInfo.extra.name, version: networkInfo.extra.version, chainId: 8453, verifyingContract: networkInfo.asset, }, types: { TransferWithAuthorization: [ { name: 'from', type: 'address' }, { name: 'to', type: 'address' }, { name: 'value', type: 'uint256' }, { name: 'validAfter', type: 'uint256' }, { name: 'validBefore', type: 'uint256' }, { name: 'nonce', type: 'bytes32' }, ], }, primaryType: 'TransferWithAuthorization', message: { from: account.address, to: networkInfo.payTo, value: BigInt(networkInfo.amount), validAfter: 0n, validBefore, nonce, }, }); ``` The resulting authorization repeats the same untrusted parameters: ```javascript const paymentPayload = { x402Version: 2, scheme: 'exact', network: 'eip155:8453', payload: { signature, authorization: { from: account.address, to: networkInfo.payTo, value: networkInfo.amount, validAfter: '0', validBefore: validBefore.toString(), nonce, }, }, }; ``` ### Technical Analysis The manual EVM pay ...[truncated 3349 chars]
Remediation
## Remediation Suggestions Validate every payment term before invoking any signing operation: 1. Require the network to equal the intended CAIP-2 identifier, such as `eip155:8453`. 2. Require the chain ID to equal `8453` and reject inconsistent network or domain values. 3. Compare `networkInfo.asset` against an immutable allowlist of official payment-token contracts for each supported network. 4. Require `networkInfo.amount` to be exactly `30000` atomic units for the advertised scan price, or enforce a lower user-configured maximum. Parse it strictly as a decimal integer and reject negative, malformed, or oversized values. 5. Validate `networkInfo.payTo` against a recipient obtained through a trusted, independently authenticated configuration. If recipients are dynamic, display the recipient and amount and require explicit user approval. 6. Allowlist the expected EIP-712 domain name and version. 7. Retain a short authorization lifetime and use a cryptographically random nonce, such as `crypto.randomBytes(32)`, rather than combining the current time with `Math.random()`. 8. Use the documented payment-identifier extension so retries cannot unintentionally create multiple charges. 9. Keep the dedicated payment wallet recommendation and enforce a low balance or wallet-level spending limit. 10. Update the “read-only” wording to clarify that scanning does not modify the analyzed token, but the Skill signs a payment authorization that can transfer funds from the payment wallet. 11. Apply the same validation helper to the viem, ethers.js, `@x402/fetch`, and managed-wallet integrations wherever the integration permits pre-signing policy checks. Example hardening logic: ```javascript const EXPECTED_NETWORK = 'eip155:8453'; const EXPECTED_CHAIN_ID = 8453; const EXPECTED_ASSET = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'; const EXPECTED_AMOUNT = 30000n; const networkInfo = paymentRequired.accepts.find( item => item.network === EX ...[truncated 863 chars]
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 (12)

External Transmission

Medium
Category
Data Exfiltration
Content
const wallet = createWallet(process.env.X402_PAYMENT_KEY);

const response = await x402Fetch('https://x402.quickintel.io/v1/scan/full', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
Confidence
60% 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
const wallet = createWallet(process.env.X402_PAYMENT_KEY);

const response = await x402Fetch('https://x402.quickintel.io/v1/scan/full', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
Confidence
60% 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
### Pattern 5: AgentWallet (frames.ag)

```javascript
const response = await fetch('https://frames.ag/api/wallets/{username}/actions/x402/fetch', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${AGENTWALLET_API_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.

External Transmission

Medium
Category
Data Exfiltration
Content
### Pattern 6: Sponge Wallet (One-Liner)

```bash
curl -sS -X POST "https://api.wallet.paysponge.com/api/x402/fetch" \
  -H "Authorization: Bearer $SPONGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
Confidence
60% 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
### Pattern 6: Sponge Wallet (One-Liner)

```bash
curl -sS -X POST "https://api.wallet.paysponge.com/api/x402/fetch" \
  -H "Authorization: Bearer $SPONGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
Confidence
50% 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
recipient: recipientFromHeader
});

const response = await fetch('https://x402.quickintel.io/v1/scan/full', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The trigger list includes very broad everyday phrases like 'is this token safe', 'scam check', and 'safe to buy', which can match normal conversation and cause the skill to activate unintentionally. In a skill that initiates paid external API calls, accidental invocation can lead to unwanted spend and unnecessary transmission of token-related queries to third parties.

External Transmission

Medium
Category
Data Exfiltration
Content
### Pattern A: Sponge Wallet (Recommended — No Raw Keys)

```bash
curl -sS -X POST "https://api.wallet.paysponge.com/api/x402/fetch" \
  -H "Authorization: Bearer $SPONGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
Confidence
86% confidence
Finding
The curl example posts scan details plus a bearer credential to an external wallet/payment processor. This is a real data egress and credential-use path; if operators copy the example into insecure environments, tokens may be exposed via shell history, process inspection, CI logs, or misconfigured telemetry.

External Transmission

Medium
Category
Data Exfiltration
Content
### Pattern A: Sponge Wallet (Recommended — No Raw Keys)

```bash
curl -sS -X POST "https://api.wallet.paysponge.com/api/x402/fetch" \
  -H "Authorization: Bearer $SPONGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
Confidence
86% confidence
Finding
The curl example posts scan details plus a bearer credential to an external wallet/payment processor. This is a real data egress and credential-use path; if operators copy the example into insecure environments, tokens may be exposed via shell history, process inspection, CI logs, or misconfigured telemetry.

External Transmission

Medium
Category
Data Exfiltration
Content
### Pattern B: AgentWallet (No Raw Keys)

```javascript
const response = await fetch('https://frames.ag/api/wallets/{username}/actions/x402/fetch', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.AGENTWALLET_API_TOKEN}`,
Confidence
88% confidence
Finding
This code sends data and an authorization bearer token to an external wallet service endpoint. Even though the API token is not hardcoded, the skill normalizes exfiltration of wallet-linked credentials and scan parameters to a third party, which expands trust boundaries and could expose financial metadata or enable abuse if the token is mishandled.

External Transmission

Medium
Category
Data Exfiltration
Content
// NEVER use your main wallet or trading wallet private key here
const wallet = createWallet(process.env.X402_PAYMENT_KEY);

const response = await x402Fetch('https://x402.quickintel.io/v1/scan/full', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ chain: 'base', tokenAddress: '0x...' }),
Confidence
93% confidence
Finding
This pattern uses a raw private key from environment variables for programmatic signing and then transmits a paid request to an external service. While the key is not directly sent, encouraging private-key-based automation materially increases the risk of key misuse, accidental exposure through logs/crashes, or compromise of a hot wallet tied to automated payments.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
Quick Intel NEVER receives your private key.
Quick Intel NEVER interacts with your tokens.
Quick Intel is READ-ONLY — no transactions, no approvals.
```

**NEVER paste private keys, seed phrases, or wallet credentials into any prompt.** Quick Intel only needs the token's contract address and chain.
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Static analysis

No suspicious patterns detected.