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
TypeScript · 0 · Jun 8, 2026 · Jun 9, 2026 · GITHUB ↗
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:292src/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:338src/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:309src/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:351src/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:388src/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:376src/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.