Inspiration

"New PayPal Scam Sends Verified Invoices With Fake Support Numbers" (Hackread, 15 Jan 2026).

A stranger gets a real PayPal invoice for a $499 charge they never made. The note says "call our billing helpline 1-888-… within 12 hours to cancel". The email really comes from PayPal, passes SPF, DKIM and DMARC, and links to a real paypal.com page. Every check people are taught to run comes back clean. Nothing is paid through the invoice, so payment-fraud checks never see it. The harm happens on the phone call: remote-access software, fake "refunds", gift cards.

The BBB Scam Tracker logged 200 reports of a PayPal-invoice variant in two weeks in 2025. Secondary coverage of the FBI IC3 2025 report puts tech-support fraud at $2.13B, with $1.04B of it lost by people aged 60 and over.

What it does

HangUp reads an invoice's text and says whether it is trying to get someone to phone a number about a charge they never ordered.

  • For the person reading it. A Chrome extension runs on the genuine PayPal invoice page and shows a plain banner: "Don't call the number in this invoice. This is a real PayPal page, but the note was written by the sender, not PayPal." A caregiver can install it once for a parent.
  • At send time. A gate in front of PayPal Invoicing v2 screens each invoice before it goes out. It allows it, holds it as a draft for a person to review, or blocks it. If the AI is unreachable, nothing is sent. It is built for any platform that sends PayPal invoices for its sellers, and it is the check PayPal itself could run.
  • Against campaigns. HangUp links one callback number across different sellers into a campaign. One click cancels every already-sent invoice in that campaign whose own text was flagged. Verified PayPal webhooks confirm each change.
  • A screening console on AG Grid. Verdict-coloured rows, the evidence quote beside each decision, quick filters, bulk release, block and cancel behind confirm dialogs, and a campaigns grid.

How we built it

invoice text → normaliser (code) → AI fills a strict form → decide (plain code) → verdict

  • Normaliser: turns 8 0 8 · 5 5 5 · O l 4 2, full-width digits and spelled-out numbers into one canonical number.
  • AI judge: Claude via OpenRouter at temperature 0, JSON only, with no tools. It treats the note as hostile data and fills a form: callback demanded, written for someone who never ordered this, brand impersonated, urgency, remote-access story, injection attempt, and evidence quotes that must appear verbatim in the text.
  • Decide: plain code applies rules to the form. The AI never decides alone, never says "safe" and never moves money.
  • PayPal (sandbox, live): Invoicing v2 create, send, list, get, cancel and delete, with a PayPal-Request-Id on every create; OAuth; webhooks verified with PayPal's verify-webhook-signature API.
  • Stack: Node.js and Express, AG Grid Community 32.3.3, a Manifest V3 extension, Playwright for tests, hosted on Render.

Challenges we ran into

  • Honest invoices have phone numbers too. "Call Dana on (503) 555-0173" from a plumber is not a scam, so a phone-number rule can't tell them apart. The AI reads what the number is for, and code decides the rest.
  • Cancelling safely. An attacker could paste an honest plumber's number into scam notes. A campaign cancel therefore only touches invoices whose own text was flagged, and the server enforces that again.
  • The gray zone. A real remote-support bill that mentions TeamViewer should be looked at, not blocked. That is the HOLD path, and the demo shows a person releasing one.
  • Not fooling ourselves. We froze and hashed the eval data before running the system on it, ran an independent review, and fixed what it found.

Accomplishments that we're proud of

  • Real text (frozen before the run): 29 real scam notes from public reports and 50 real billing passages from 32 businesses' public pages. HangUp caught 27 of 29 scams and flagged 1 of 50 honest passages. A phone-number rule caught the same 27 but flagged 16 of 50. The honest rows are public billing text, not sent invoice notes, and n is small.
  • A second real set, also frozen first: 16 of 16 scams caught, 0 of 25 honest passages flagged.
  • Live PayPal, end to end: send, backfill scan, gate decisions, release, campaign cancel and a re-fetch showing CANCELLED, run repeatedly on the hosted app against the sandbox.
  • Safety properties with tests: fails closed, handles prompt injection, and a retry can never create a duplicate invoice.

What we learned

  • A rule that looks obviously right (a phone number plus a charge claim) is wrong on real honest billing text. Measuring on real text changed our design.
  • Domain and hosting renewals are our weakest family, because a real registrar's notice can read like the scam. We wrote that down instead of retuning on data we had already seen.
  • Only PayPal can screen a scammer's own account. Anyone else can protect the person reading the invoice and the platforms that send invoices.

What's next for HangUp

  • Re-screen an invoice when its note is edited after sending.
  • A forward-to-check email address, so it works from a phone with nothing to install.
  • Publish the extension on the Chrome Web Store, and run the Gmail script (tested only on a Gmail-like page so far) on live Gmail.
  • Publish the eval as an open benchmark that other tools can be scored on.

Built With

Share this project:

Updates

Submission history