BACK TO SEARCH
markswendsen-code/mcp-cashappcritical
MCP server for Cash App - let AI agents send and receive money
This MCP server automates Cash App operations via browser automation, allowing AI agents to log in, check balances, send/receive money, manage transac...
purpose: This MCP server automates Cash App operations via threat: local with credentials
RISK SCORE
0/ 100 risk
high findings+50
medium findings+75
capped at100
VULNERABILITY ANALYSIS · 7 findings in 7 blocks2 HIGH · 5 MEDIUM
HIGH1 finding
src/index.ts:239
239case "cashapp_login": {
240 const { email_or_phone, password } = args as {
241 email_or_phone: string;
242 password: string;
243 };
244 const result = await login(email_or_phone, password);src/index.ts:239
// Local-with-credentials MCP; requires compromised LLM or local access to intercept stdio.
EXPLAINThe cashapp_login tool accepts email/phone and password as plaintext arguments. These credentials are transmitted over stdio and could be logged or intercepted by any process with access to the MCP server's I/O.
IMPACTAn attacker with access to the MCP server's stdio or logs can obtain the user's Cash App credentials, leading to account takeover.
FIXUse environment variables or a secure credential store instead of passing credentials as tool arguments. Consider using OAuth or token-based authentication.
HIGH1 finding
src/browser.ts:295
295export async function sendMoney(
296 recipient: string,
297 amount: number,
298 note: string
299): Promise<{ success: boolean; message: string; transactionId?: string }> {
300 const session = await getBrowser();
301 const { page } = session;
302 try {
303 await page.goto(CASHAPP_URL, { waitUntil: "networkidle" });
304 await page.waitForTimeout(1000);
305 const payBtn = await page.waitForSelector(...);
306 await payBtn.click();
307 ...
308 const confirmBtn = await page.waitForSelector(...);
309 await confirmBtn.click();src/index.ts:292→src/browser.ts:295
// Local-with-credentials MCP; requires compromised LLM to exploit.
EXPLAINThe sendMoney tool automates the entire payment flow without requiring explicit user confirmation for each transaction. A compromised LLM could initiate unauthorized payments.
IMPACTAn attacker controlling the LLM could send money to arbitrary recipients, draining the user's Cash App balance.
FIXAdd a confirmation step that requires user approval before executing financial transactions. Implement rate limiting and transaction limits.
MEDIUM1 finding
src/browser.ts:500
500export async function acceptRequest(
501 requestId: string
502): Promise<{ success: boolean; message: string }> {
503 const session = await getBrowser();
504 const { page } = session;
505 try {
506 await page.goto(`${CASHAPP_URL}/account/activity/${requestId}`, {
507 waitUntil: "networkidle",
508 });
509 await page.waitForTimeout(1500);
510 const acceptBtn = await page.waitForSelector(...);
511 await acceptBtn.click();src/index.ts:338→src/browser.ts:500
// Local-with-credentials MCP; requires compromised LLM to exploit.
EXPLAINThe acceptRequest tool automatically accepts payment requests, which sends money to the requester. A compromised LLM could accept fraudulent requests without user awareness.
IMPACTAn attacker could trick the LLM into accepting payment requests, causing unauthorized funds transfer.
FIXRequire explicit user confirmation before accepting payment requests. Add a confirmation dialog or require a separate approval step.
MEDIUM1 finding
src/browser.ts:391
391export async function requestMoney(
392 recipient: string,
393 amount: number,
394 note: string
395): Promise<{ success: boolean; message: string }> {
396 const session = await getBrowser();
397 const { page } = session;
398 try {
399 await page.goto(CASHAPP_URL, { waitUntil: "networkidle" });
400 await page.waitForTimeout(1000);
401 const requestBtn = await page.waitForSelector(...);
402 await requestBtn.click();src/index.ts:309→src/browser.ts:391
// Local-with-credentials MCP; requires compromised LLM to exploit.
EXPLAINThe requestMoney tool automates sending payment requests. A compromised LLM could spam requests to arbitrary users, causing annoyance or social engineering attacks.
IMPACTAn attacker could use the LLM to send fraudulent payment requests to the user's contacts, potentially leading to scams.
FIXAdd user confirmation before sending payment requests. Implement rate limiting and recipient validation.
MEDIUM1 finding
src/browser.ts:532
532export async function declineRequest(
533 requestId: string
534): Promise<{ success: boolean; message: string }> {
535 const session = await getBrowser();
536 const { page } = session;
537 try {
538 await page.goto(`${CASHAPP_URL}/account/activity/${requestId}`, {
539 waitUntil: "networkidle",
540 });
541 await page.waitForTimeout(1500);
542 const declineBtn = await page.waitForSelector(...);
543 await declineBtn.click();src/index.ts:351→src/browser.ts:532
// Local-with-credentials MCP; requires compromised LLM to exploit.
EXPLAINThe declineRequest tool automatically declines payment requests. A compromised LLM could decline legitimate requests, causing missed payments or disputes.
IMPACTAn attacker could cause the user to miss important payment requests by automatically declining them.
FIXRequire user confirmation before declining payment requests. Notify the user of declined requests.
MEDIUM1 finding
src/browser.ts:647
647export async function getCardInfo(): Promise<{
648 cardNumber: string;
649 status: string;
650 type: string;
651 expiryDate?: string;
652}> {
653 const session = await getBrowser();
654 const { page } = session;
655 await page.goto(`${CASHAPP_URL}/card`, { waitUntil: "networkidle" });
656 await page.waitForTimeout(2000);
657 let cardNumber = "Not available";
658 ...
659 const cardMatch = content.match(/\*{4}\s*\d{4}|\d{4}\s*\d{4}\s*\d{4}\s*\d{4}/);
660 if (cardMatch) cardNumber = cardMatch[0];src/index.ts:388→src/browser.ts:647
// Local-with-credentials MCP; requires compromised LLM to exploit.
EXPLAINThe getCardInfo tool retrieves sensitive card information including the card number (last 4 digits or full number) and expiry date. This information could be exposed to a compromised LLM.
IMPACTAn attacker could obtain partial card details, which combined with other information could be used for fraud.
FIXMask card numbers and limit exposure to only the last 4 digits. Avoid returning expiry dates unless absolutely necessary.
MEDIUM1 finding
src/browser.ts:611
611export async function getBitcoinBalance(): Promise<{
612 btcBalance: string;
613 usdValue: string;
614}> {
615 const session = await getBrowser();
616 const { page } = session;
617 await page.goto(`${CASHAPP_URL}/btc`, { waitUntil: "networkidle" });
618 await page.waitForTimeout(2000);
619 let btcBalance = "0";
620 let usdValue = "$0.00";src/index.ts:376→src/browser.ts:611
// Local-with-credentials MCP; requires compromised LLM to exploit.
EXPLAINThe getBitcoinBalance and getContacts tools expose financial and personal information that could be used for targeted attacks.
IMPACTAn attacker could learn the user's Bitcoin holdings and contact list, enabling social engineering or targeted theft.
FIXConsider whether these tools are necessary. If so, add user confirmation before returning sensitive data.
◷ 6/9/2026
Findings are produced by automated LLM analysis and may include false positives or miss issues. Verify independently before acting.