Back to skill

Security audit

Bob P2P - Beta

Security checks for vulnerabilities and agentic risk

Overview

This skill matches its marketplace purpose, but it handles real wallet secrets and payments in ways that could expose funds or cause unintended spending.

Review carefully before installing. Use only a dedicated low-balance wallet, avoid storing a primary wallet mnemonic/private key in this client, confirm exact recipient and price out of band before calls, and treat downloaded provider results as untrusted. The skill should add safer secret storage, payment confirmation and spending limits, fixed token amount handling, path containment for downloads, endpoint authorization, and a reproducible dependency lockfile before ordinary use.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (6)

T09 · Insecure Skill Coding Practices

Error
Location
client/src/solana/index.js:274
Finding
Incorrect SPL Token Decimal Conversion Can Cause 1,000× Overpayment<![CDATA[ ## Vulnerability Details **File Location**: `client/src/solana/index.js:274-280` **Vulnerability Type**: Incorrect cryptocurrency amount conversion **Risk Level**: Critical ### Vulnerable Code ```js const transferInstruction = createTransferInstruction( sourceTokenAccount, destTokenAccount, this.publicKey, amount * Math.pow(10, 9) // Convert to smallest unit ); ``` The same module assumes that BOB has six decimal places when verifying transfers: ```js return { amount: amount / Math.pow(10, 6), // Convert from smallest unit (BOB has 6 decimals) recipient, tokenMint, source: accountKeys[sourceIndex].toBase58() }; ``` ### Technical Analysis The payment sender converts the human-readable token amount to base units using `10^9`, while the payment verification logic converts base units back using `10^6`. Under the module's stated assumption that BOB has six decimals, the sender creates a transfer 1,000 times larger than intended. For example, a displayed price of `0.05 BOB` is converted into `50,000,000` base units. With six decimals, that value represents `50 BOB`, not `0.05 BOB`. The code also uses JavaScript floating-point arithmetic for token amounts. This can introduce rounding or precision errors and is unsuitable for constructing exact on-chain integer amounts. ### Attack Path 1. A consumer selects an API advertised at a particular BOB price. 2. The HTTP provider or P2P listing supplies the price to the client. 3. `sendPayment()` multiplies that price by `10^9`. 4. The resulting transaction is signed with the consumer's private key and submitted to Solana. 5. If the mint uses the six decimals assumed elsewhere in the module, the provider receives 1,000 times the intended amount. A malicious provider can deliberately encourage calls with an apparently inexpensive price and benefit from the erroneous conversion. ### Impact Assessment Successful exploitation or ordinary use can cause direct and irreversible ...[truncated 258 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Query the mint's actual decimal count from Solana instead of hardcoding it. - Convert amounts with integer or `BigInt` arithmetic. - Use a decimal parsing routine that rejects values with excessive fractional precision. - Reject `NaN`, infinity, negative values, zero values where inappropriate, and amounts exceeding configured limits. - Present the exact base-unit and human-readable amount to the user before signing. - Add unit and integration tests for fractional prices, maximum values, and the configured mint's actual decimals. - Ensure sending and verification use the same decimal value and conversion utility. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
client/src/consumer/index.js:243
Finding
Remote Provider Data Controls Automatic Cryptocurrency Payments Without Price Authorization<![CDATA[ ## Vulnerability Details **File Location**: `client/src/consumer/index.js:243-254` **Additional Location**: `scripts/call.sh:51-58,68-75` **Vulnerability Type**: Untrusted recipient and price used for automatic payment **Risk Level**: High ### Vulnerable Code The call script obtains the payment recipient from aggregator-controlled JSON: ```bash # Parse provider info (cross-platform compatible) PROVIDER_URL=$(echo "$API_INFO" | grep -o '"endpoint":"[^"]*"' | cut -d'"' -f4) PROVIDER_WALLET=$(echo "$API_INFO" | grep -o '"address":"[^"]*"' | head -1 | cut -d'"' -f4) PRICE=$(echo "$API_INFO" | grep -o '"amount":[0-9.]*' | head -1 | cut -d':' -f2) if [ -z "$PROVIDER_URL" ] || [ -z "$PROVIDER_WALLET" ]; then echo "❌ Could not parse provider details" echo " API response: $API_INFO" exit 1 fi ``` It then passes the remotely supplied wallet to the execution workflow: ```bash node src/cli/consumer-execute.js "$API_ID" \ --config config.json \ --provider "$PROVIDER_URL" \ --provider-wallet "$PROVIDER_WALLET" \ --body "$BODY" ``` The payment amount is independently accepted from the provider's queue response: ```js // Step 1: Request queue position console.log('Step 1: Requesting queue position...'); const queueData = await this.requestQueue(providerUrl, apiId); console.log(`Queue code: ${queueData.code}`); console.log(`Position: ${queueData.position}`); console.log(`Price: ${queueData.price} ${this.config.token.symbol}`); console.log(`Expires in: ${queueData.expirySeconds} seconds\n`); // Step 2: Send payment console.log('Step 2: Sending payment...'); const signature = await this.sendPayment(providerWallet, queueData.price); console.log(`Transaction: ${signature}\n`); ``` ### Technical Analysis The aggregator determines the provider URL and recipient wallet, while the selected provider determines `queueData.price`. The client does not cryptographically bind these values to a trusted listing, compare the queue price with ...[truncated 1413 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require explicit confirmation that displays the exact mint, recipient, advertised price, queue price, and base-unit amount. - Add configurable per-call, daily, and total spending limits. - Reject any queue price that differs from the signed or previously approved listing price. - Require API listings to be signed by the provider and verify the signature before payment. - Cryptographically bind the API identifier, endpoint, recipient wallet, token mint, price, and expiration. - Parse aggregator responses with a JSON parser and strict schema validation rather than `grep`. - Validate that amounts are finite, positive, within expected precision, and below configured limits. - Consider constructing the transaction for external wallet approval instead of storing and using a raw private key. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
client/src/consumer/index.js:157
Finding
Provider-Controlled Result Filename Allows Arbitrary File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `client/src/consumer/index.js:157-187` **Vulnerability Type**: Path traversal and arbitrary file overwrite **Risk Level**: Critical ### Vulnerable Code ```js async downloadResult(resultUrl, outputPath) { const response = await axios.get(resultUrl, { responseType: 'stream', timeout: 60000 }); const writer = fs.createWriteStream(outputPath); response.data.pipe(writer); return new Promise((resolve, reject) => { writer.on('finish', resolve); writer.on('error', reject); }); } /** * Download job result file via P2P streaming * * @param {string} providerUrl - Provider endpoint * @param {string} jobId - Job identifier * @param {string} resultFilename - Result filename * @returns {Promise<string>} - Local file path */ async downloadJobResult(providerUrl, jobId, resultFilename) { const downloadUrl = `${providerUrl}/job/${jobId}/download`; const localPath = path.join(this.outputPath, resultFilename); console.log(`Downloading result from provider via P2P...`); await this.downloadResult(downloadUrl, localPath); console.log(`Result saved to: ${localPath}`); return localPath; } ``` The remote filename is consumed automatically after polling: ```js if (completedJob.resultFilename && this.outputPath) { console.log('\nStep 5: Downloading result file...'); const localFilePath = await this.downloadJobResult( providerUrl, completedJob.jobId, completedJob.resultFilename ); completedJob.localFilePath = localFilePath; } ``` ### Technical Analysis `resultFilename` originates in the remote provider's job-status response. It is passed directly to `path.join()` without rejecting absolute paths, path separators, or `..` traversal components. `path.join()` normalizes traversal but does not guarantee that the resulting path remains inside `this.outputPath`. `fs.createWriteStream()` then creates or ...[truncated 1171 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Treat all provider-supplied filenames as untrusted. - Replace the supplied name with `path.basename(resultFilename)` or generate a local random filename. - Reject names containing `/`, `\`, null bytes, drive prefixes, or traversal components. - Resolve both the output directory and destination path, then verify that the destination starts with the canonical output-directory prefix. - Open files with exclusive creation where overwriting is unnecessary. - Download to a securely created temporary file and atomically rename it after validation. - Enforce a maximum response size and expected content type. - Do not automatically write provider content outside a dedicated directory with restrictive permissions. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/setup.sh:143
Finding
Wallet Mnemonic Is Entered Visibly and Stored Without Enforced Restrictive Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh:143-151` **Additional Location**: `scripts/configure.sh:53-64` **Vulnerability Type**: Insecure handling of plaintext wallet secrets **Risk Level**: High ### Vulnerable Code From the setup script: ```bash read -p "Wallet address: " WALLET_ADDRESS echo "Private key (will be visible - mnemonic or key):" read -p "> " PRIVATE_KEY if [ -n "$WALLET_ADDRESS" ] && [ -n "$PRIVATE_KEY" ]; then cat > "$CONFIG_FILE" << CONFIGEOF { "wallet": { "address": "$WALLET_ADDRESS", "privateKey": "$PRIVATE_KEY" ``` The configuration script repeats the same pattern: ```bash read -p "Wallet address: " WALLET_ADDRESS echo "Private key (mnemonic or key):" read -p "> " PRIVATE_KEY if [ -n "$WALLET_ADDRESS" ] && [ -n "$PRIVATE_KEY" ]; then # Create new config preserving other settings RESULTS_PATH="$HOME/.bob-p2p/results" cat > "$CONFIG_FILE" << CONFIGEOF { "wallet": { "address": "$WALLET_ADDRESS", "privateKey": "$PRIVATE_KEY" ``` ### Technical Analysis The private key or mnemonic is collected with ordinary `read`, so terminal echo remains enabled. The secret can be exposed through shoulder surfing, screen sharing, terminal recording, or session-capture tooling. The scripts then store the complete secret in plaintext JSON. They do not set `umask 077`, use a secure secret store, or explicitly apply `chmod 600`. File readability therefore depends on the user's ambient umask and environment. A mnemonic provides control over the derived wallet and is substantially more sensitive than an ordinary API credential. ### Attack Path 1. A user follows the documented setup or reconfiguration process. 2. The user types a wallet mnemonic or private key into an echoed prompt. 3. The secret may be captured by observers or terminal-recording systems. 4. The script writes the secret to `~/.bob-p2p/client/config.json`. 5. If file permissions permit access, another lo ...[truncated 491 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Prefer an external wallet signer, hardware wallet, or wallet-adapter flow so the Skill never stores the private key. - If local storage is unavoidable, use an operating-system credential store or encrypted keystore. - Read secrets with terminal echo disabled, such as `read -s`. - Set `umask 077` before creating directories or configuration files. - Create the configuration atomically and enforce mode `0600`. - Verify the file owner and permissions every time the configuration is loaded. - Avoid supporting seed phrases where a narrowly scoped signing interface is sufficient. - Warn users against using a primary wallet and recommend a low-balance dedicated wallet. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
client/src/provider/server.js:186
Finding
Job Results and Generated Files Are Exposed Without Consumer Authorization<![CDATA[ ## Vulnerability Details **File Location**: `client/src/provider/server.js:186-240` **Vulnerability Type**: Missing authorization on job and download endpoints **Risk Level**: Medium ### Vulnerable Code ```js // Get job status this.app.get('/job/:jobId', async (req, res) => { try { const { jobId } = req.params; const job = await this.jobs.getJob(jobId); res.json({ jobId: job.jobId, apiId: job.apiId, status: job.status, progress: job.progress, progressMessage: job.progressMessage, result: job.result, resultFilename: job.resultFilename, error: job.error, createdAt: job.createdAt, startedAt: job.startedAt, completedAt: job.completedAt }); } catch (error) { res.status(404).json({ error: error.message }); } }); // Download job result file (P2P streaming) this.app.get('/job/:jobId/download', async (req, res) => { try { const { jobId } = req.params; const job = await this.jobs.getJob(jobId); if (job.status !== 'completed') { return res.status(400).json({ error: 'Job not completed yet' }); } if (!job.resultFilename) { return res.status(404).json({ error: 'No result file available for this job' }); } const filepath = path.join(this.jobs.resultStorage, job.resultFilename); if (!fs.existsSync(filepath)) { return res.status(404).json({ error: 'Result file not found on disk' }); } // Stream the file to consumer res.sendFile(filepath); } catch (error) { res.status(404).json({ error: error.message }); } }); ``` ### Technical Analysis The provider retrieves jobs solely by `jobId`. Neither endpoint authenticate ...[truncated 1219 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Authenticate every status and download request. - Require a wallet-signed challenge and verify that the signing wallet matches the job's consumer address. - Alternatively, issue short-lived, high-entropy capability tokens bound to a specific job and operation. - Expire download capabilities and support revocation. - Avoid returning full result content from unauthenticated status endpoints. - Apply access-control checks before looking up or returning job metadata. - Rate-limit failed authorization attempts and avoid exposing whether unauthorized job IDs exist. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/setup.sh:77
Finding
Setup Installs Mutable Dependencies Without a Lockfile<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh:77-80` **Additional Location**: `client/package.json:29-53` **Vulnerability Type**: Non-reproducible dependency installation and lifecycle-script exposure **Risk Level**: Medium ### Vulnerable Code ```bash # Install dependencies echo "" echo "📦 Installing Node.js dependencies..." cd "$CLIENT_DIR" npm install --silent 2>/dev/null || npm install ``` The dependency manifest uses mutable version ranges, including: ```json "dependencies": { "@chainsafe/libp2p-noise": "^17.0.0", "@libp2p/bootstrap": "^12.0.11", "@libp2p/circuit-relay-v2": "^4.1.3", "@solana/spl-token": "^0.3.9", "@solana/web3.js": "^1.87.6", "axios": "^1.6.0", "better-sqlite3": "^12.6.2", "express": "^4.18.2", "libp2p": "^3.1.3", "mongodb": "^6.3.0", "pg": "^8.11.3", "tedious": "^16.6.1" } ``` No dependency lockfile was present in the audited project structure. ### Technical Analysis `npm install` resolves dependency and transitive-dependency versions at installation time. Because the manifest uses caret ranges and no reviewed lockfile is included, two users can receive different package versions. NPM lifecycle scripts may execute during installation. A compromised package release or dependency account can therefore execute code under the user running `scripts/setup.sh`, even though that package version was not part of the audited artifact. No malicious dependency was proven during this static audit; the issue is the unsafe and non-reproducible installation model. ### Attack Path 1. A direct or transitive dependency publisher account is compromised, or a malicious release is published within an allowed version range. 2. A user runs `scripts/setup.sh`. 3. `npm install` resolves the newly published version because no lockfile constrains the dependency graph. 4. The package's lifecycle script executes with the user's privileges. 5. The malicious package can access user files, including the plai ...[truncated 403 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Generate and commit a reviewed `package-lock.json`. - Replace `npm install` with `npm ci` so installation fails if the lockfile and manifest differ. - Pin security-sensitive dependencies to reviewed versions. - Review direct and transitive package lifecycle scripts. - Use `npm ci --ignore-scripts` where native builds or required lifecycle steps are not needed. - Perform dependency vulnerability and provenance checks in CI. - Update dependencies through reviewed, reproducible pull requests rather than resolving mutable versions during end-user setup. - Consider separating optional database and P2P packages to reduce the dependency and lifecycle-script attack surface. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (93)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill asks users to store a wallet private key or mnemonic locally and run setup/configuration scripts, while presenting itself as a marketplace client. Even if that behavior matches the intended design, collecting high-value crypto secrets into a local config file materially increases theft risk and is more dangerous in a skill that also performs shell and network actions.

External Script Fetching

High
Category
Supply Chain
Content
echo ""

# Fetch and pretty-print
RESULT=$(curl -s "$AGGREGATOR/api/$API_ID")

# Try python, then node, then raw output
if command -v python3 &> /dev/null; then
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Missing User Warnings

High
Confidence
98% confidence
Finding
The script prompts for a wallet private key and writes it directly into config.json in plaintext under the user's home directory, with no warning, encryption, or permission hardening. In the context of a Solana/$BOB marketplace client, compromise of this file can directly enable theft of funds, unauthorized transactions, and impersonation of the user on the network.

Missing User Warnings

High
Confidence
98% confidence
Finding
The setup script interactively prompts for a Solana private key or mnemonic and writes it directly into config.json in plaintext under the user's home directory. This is dangerous because wallet secrets can be exposed through local file compromise, backups, shell observation/shoulder-surfing, or accidental disclosure, leading to theft of on-chain funds and unauthorized transactions. The skill context increases risk because this wallet is intended to hold and spend real Solana-based assets on mainnet.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill instructs users to run shell scripts and perform network operations, but it declares no explicit tool scope or permission boundaries. In an agent environment, missing scope metadata increases the chance that the skill can be invoked with broader-than-expected shell/network access and makes review and enforcement harder.

Session Persistence

Medium
Category
Rogue Agent
Content
This will:
1. Clone the bob-p2p-client repository
2. Install Node.js dependencies
3. Create config from template
4. Prompt you for wallet configuration

### Manual Setup
Confidence
76% confidence
Finding
The setup flow creates persistent local configuration and prompts for wallet configuration, which implies session persistence of sensitive operational state. In this context, persistence becomes risky because the stored state includes or may lead to storing cryptocurrency credentials and long-lived connectivity settings that survive beyond the immediate task.

Missing User Warnings

Medium
Confidence
99% confidence
Finding
The setup instructions tell users to place a Solana wallet private key or mnemonic directly into config.json, but the immediate step lacks a clear warning that this stores highly sensitive credentials in plaintext. Plaintext seed phrase storage makes wallet compromise much more likely through filesystem exposure, backups, logs, malware, or accidental commits.

Static analysis

No suspicious patterns detected.