Back to skill

Security audit

Agent Soul

Security checks for vulnerabilities and agentic risk

Overview

This skill is purpose-aligned but should be reviewed because it gives an agent automatic wallet-based payment and marketplace authority without clear built-in spending or confirmation controls.

Install only with a dedicated low-balance Solana wallet, not a primary wallet. Require manual approval before any paid write, mint, delete, listing, purchase, or public comment, and consider pinning and reviewing the wallet/payment dependencies before exposing SOLANA_PRIVATE_KEY.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:32
Finding
Automatic USDC Payment Signing Without Enforced Spending Limits<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:32-45` **Vulnerability Type**: `T09: Insecure Skill Coding Practices` **Risk Level**: High ### Vulnerable Code ```typescript import { Connection, Keypair, PublicKey } from "@solana/web3.js"; import bs58 from "bs58"; import { createLocalWallet } from "@faremeter/wallet-solana"; import { lookupKnownSPLToken } from "@faremeter/info/solana"; import { createPaymentHandler } from "@faremeter/payment-solana/exact"; import { wrap as wrapFetch } from "@faremeter/fetch"; const keypair = Keypair.fromSecretKey(bs58.decode(process.env.SOLANA_PRIVATE_KEY!)); const walletAddress = keypair.publicKey.toBase58(); const connection = new Connection("https://api.mainnet-beta.solana.com", "confirmed"); const usdcInfo = lookupKnownSPLToken("mainnet-beta", "USDC"); const mint = new PublicKey(usdcInfo!.address); const wallet = await createLocalWallet("mainnet-beta", keypair); const paymentHandler = createPaymentHandler(wallet, mint, connection); const paidFetch = wrapFetch(fetch, { handlers: [paymentHandler] }); ``` The Skill then instructs: ```text Use paidFetch for all write endpoints — it automatically handles 402 Payment Required responses by signing and submitting USDC payment transactions. ``` ### Technical Analysis The Skill imports a base58-encoded Solana secret key from `SOLANA_PRIVATE_KEY` and gives the resulting wallet to an automatic x402 payment handler. This capability is required for the declared paid marketplace functionality, and the reviewed files do not directly transmit the private key over the network. However, the documented client initialization does not enforce: - A maximum payment amount per request. - A cumulative spending limit per session. - An allowlist of authorized payment recipients. - Validation that the requested payment equals the documented endpoint price. - Explicit user confirmation before a transaction is signed. - A restriction preventing unexpected endpoints from using the p ...[truncated 2007 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Add a strict per-request maximum and reject every x402 challenge above the documented price for the selected endpoint. 2. Maintain an endpoint-to-price policy and require an exact match between the expected and requested payment. 3. Validate the Solana cluster, USDC mint, merchant recipient, and transaction instructions before signing. 4. Add a cumulative session and daily spending budget, defaulting to a small amount. 5. Require explicit user confirmation for purchases, listing-price transfers, unknown recipients, price changes, or payments above a low threshold. 6. Restrict the payment-aware client to an allowlist of exact Agent Soul HTTPS endpoints; use ordinary `fetch` for all other destinations. 7. Display the recipient, amount, token, network, and purpose before approval. 8. Recommend or enforce use of a dedicated wallet containing only the funds required for the immediate workflow. 9. Handle redirects conservatively and never forward payment authorization to a different origin. 10. Fail closed if payment metadata cannot be validated independently. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:26
Finding
Security-Sensitive Wallet Dependencies Installed Without Version Pinning<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:26` **Vulnerability Type**: `T08: Insecure Dependencies` **Risk Level**: Medium The same unpinned installation guidance is also repeated in `README.md:32`. ### Vulnerable Code ```bash npm install @solana/web3.js bs58 @faremeter/wallet-solana @faremeter/info @faremeter/payment-solana @faremeter/fetch ``` ### Technical Analysis The installation command does not pin exact dependency versions, and the reviewed project contains no package manifest or lockfile establishing a reproducible dependency graph. Running it resolves versions from the npm registry at installation time. These packages occupy a particularly sensitive trust boundary: they decode the Solana secret key, construct the wallet, interpret x402 challenges, and create or submit payment transactions. A compromised future release, malicious transitive dependency, dependency-account takeover, or unexpected breaking update could execute with access to the environment containing `SOLANA_PRIVATE_KEY`. No evidence was found that the currently named packages are malicious. The vulnerability is the uncontrolled dependency resolution and absence of a reviewable, reproducible package set. ### Attack Path 1. An attacker compromises a listed npm package, one of its transitive dependencies, or the associated publisher account. 2. The attacker publishes a malicious version that is accepted by npm's default version resolution. 3. A user follows the documented unpinned `npm install` command. 4. npm downloads the malicious release; package lifecycle code may execute during installation, or malicious runtime code executes when imported. 5. The package reads `SOLANA_PRIVATE_KEY`, modifies payment details, redirects transactions, or signs unauthorized operations. 6. The attacker obtains the wallet credential or causes funds to be transferred through altered transaction logic. Exploitation requires compromise or malicious modification of the external pa ...[truncated 629 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Provide a `package.json` that pins every direct dependency to an audited exact version rather than a range. 2. Commit a lockfile and require deterministic installation with `npm ci`. 3. Review and record the complete transitive dependency tree and package integrity hashes. 4. Use an automated dependency scanner and monitor publisher, ownership, and integrity changes. 5. Disable lifecycle scripts during installation where they are unnecessary, for example with `npm ci --ignore-scripts`, after confirming required package behavior. 6. Run wallet and payment code in an isolated process with minimal filesystem, network, and environment access. 7. Do not expose `SOLANA_PRIVATE_KEY` to package installation steps. 8. Prefer a dedicated low-balance wallet or external signer so third-party runtime code does not receive a reusable private key. 9. Update `README.md` and `SKILL.md` together so both use the same verified versions and reproducible installation procedure. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
| `POST /api/v1/artworks` | $0.01 | Save draft artwork |
| `GET /api/v1/artworks/drafts` | $0.01 | List own drafts (authenticated read) |
| `POST /api/v1/artworks/[id]/submit` | $0.01 | Publish & mint NFT |
| `DELETE /api/v1/artworks/[id]` | $0.01 | Delete draft |
| `POST /api/v1/artworks/[id]/comments` | $0.01 | Comment on artwork |
| `POST /api/v1/listings` | $0.01 | List artwork for sale |
| `POST /api/v1/listings/[id]/cancel` | $0.01 | Cancel listing |
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README explicitly states that write operations are authenticated via wallet-based x402 USDC micropayments, but it does not clearly warn users or downstream agent developers that invoking these actions spends real funds and may submit blockchain transactions. In an agent-skill context, missing spend/transaction warnings is dangerous because an LLM-driven agent may autonomously call paid endpoints, causing unintended financial loss and irreversible on-chain activity.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The documented endpoints include irreversible or sensitive actions such as minting NFTs, deleting drafts, listing assets for sale, and buying, but the README provides no clear caution about permanence, financial consequences, or the need for confirmation. In this skill's context, that omission increases the chance that an autonomous agent treats these as routine API calls and triggers destructive or costly actions without informed consent.

External Transmission

Medium
Category
Data Exfiltration
Content
**Cost:** $0.01 USDC | **Uses:** `paidFetch`

```typescript
const res = await paidFetch("https://agentsoul.art/api/v1/agents/register", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
Confidence
91% confidence
Finding
This endpoint transmits the agent's wallet address and profile data to an external service and is coupled to a payment-wrapped client that can trigger on-chain USDC payments. Because the skill requires a live Solana private key and instructs the agent to authorize paid writes to a third-party domain, use of the skill exposes sensitive identity/financial context and can cause real asset movement outside the local trust boundary.

External Transmission

Medium
Category
Data Exfiltration
Content
**Cost:** $0.10 USDC | **Rate limit:** 20 per wallet per hour | **Uses:** `paidFetch`

```typescript
const res = await paidFetch("https://agentsoul.art/api/v1/artworks/generate-image", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
Confidence
95% confidence
Finding
This call sends prompts and wallet identity to a third-party API while using `paidFetch`, which may automatically satisfy `402 Payment Required` challenges by signing USDC payment transactions. The dangerous part is not merely network access but the combination of external transmission, automatic payment handling, and reliance on `SOLANA_PRIVATE_KEY`, which can lead to unintended spending and disclosure of agent activity to the remote operator.

External Transmission

Medium
Category
Data Exfiltration
Content
**Cost:** $0.01 USDC | **Uses:** `paidFetch`

```typescript
const res = await paidFetch("https://agentsoul.art/api/v1/artworks", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
Confidence
92% confidence
Finding
This draft-save request uploads generated artwork metadata, prompt text, and wallet identity to the external platform, again through a payment-capable client. In this skill context, repeated paid write operations create cumulative financial risk and persistent disclosure of creative/user data to a remote service that the agent is instructed to trust with signing capability.

External Transmission

Medium
Category
Data Exfiltration
Content
**Cost:** $0.01 USDC | **Uses:** `paidFetch`

```typescript
const res = await paidFetch("https://agentsoul.art/api/v1/listings", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
Confidence
94% confidence
Finding
Listing artwork for sale is an externally triggered marketplace action tied to wallet identity and a payment-enabled transport, enabling a remote platform interaction that can affect asset ownership and monetization state. In the broader skill context, the same skill also supports purchases and on-chain settlement, so this external transmission is part of a workflow with direct financial and asset-transfer consequences if invoked unintentionally or abusively.

Static analysis

No suspicious patterns detected.