Inspiration
Business email compromise was the second-largest source of cybercrime losses the FBI tracked in 2025: over 3 billion dollars. What struck me is how ordinary it looks. There's no malware and no suspicious link, just a normal email from someone you already pay, asking you to send this month's invoice to a new account.
I wanted to solve it the way it would be solved in the real world. The easy version would have been a web page where you upload an email and get back "fraud" or "not fraud". But nobody copies emails into a website before paying a bill. So I started from the user, an accounts payable clerk at a company, and asked where the decision actually happens. The answer is the inbox, at the moment they're about to pay. That's why BEC Guard lives inside the inbox.
What it does
BEC Guard is a backend service, deployed on Render, that runs all the checks with Nemotron models, plus a lightweight Gmail add-on that connects it to the inbox. The add-on sends new emails and mailbox changes to the BEC Guard API and shows the result next to the email. (The backend works with any email service: an Outlook add-in would call the same API. Gmail is the one I connected because it allows this kind of integration for free; the Outlook integration needs a paid Microsoft Azure account, and publishing a Gmail add-on for other companies needs Google's review and a security assessment, both outside this hackathon's resources. See "What's next".)
When an email asks for money or sensitive data, BEC Guard shows a card next to the email: Verify before paying, Looks unusual or No issues found. The card has three sections:
- The sender: is this really who it claims to be? It compares the address with the vendor records and the staff directory, and looks for lookalike domains, free email accounts and a known name on a new address.
- The company: is the company real? A Nemotron web-search agent finds its official website and phone number.
- The request: does it match the records? It compares the bank account with the one we've always paid, including details inside PDF invoices, and checks for a change of payment method and for pressure or secrecy.
Warnings based on the records show the evidence behind them, such as the last six invoices paid to account ••4821, and when the email claims to come from a vendor or colleague on file, the card gives a phone number to call from the company's own records.
It also watches the organization's own mailbox for signs of takeover: new filters or forwarding, bank details sent from the account, and sent mail deleted soon after sending. When it sees these, it shows a banner and emails the compliance team. Risky emails also get a label in the inbox.
How we built it
I designed the solution myself. I broke the problem down by asking two questions of every attack: how does the attacker get a trusted voice (fake, hack, or a second channel), and what do they ask for? That led to three parallel checks on every money or data request: an entity check, an org check and a content check. A deterministic rules-based scorer makes the decision, and Nemotron Ultra explains it in plain words.
- Models: NVIDIA Nemotron on Nebius Token Factory. Nano screens every email, Super does the judgement and runs the web-search agent with Tavily, Super VL reads PDF attachments, and Ultra writes the card.
- Backend: FastAPI, with the company's vendor records and staff directory as the source of truth. It exposes one API that any mail client can call, with a separate key for each company.
- Gmail add-on: Google Apps Script, a thin connector to the backend API. It sends new mail and mailbox changes to the API every minute and shows the card in the sidebar.
- Website: React, with an animated story of the problem, a sample inbox to try it, and the production plan.
- Hosting: the base version is deployed on Render's free tier.
For the code I used Claude Code with a set of working rules and custom skills: grooming the idea, planning before building, tests first, and keeping a project journal of every decision. I read what it produced rather than following it blindly, and corrected it in many places, from wrong assumptions to claims I couldn't back.
Challenges we ran into
- Apps Script timing. The add-on can only check the mailbox once a minute, Gmail doesn't redraw labels until you refresh, and the sidebar has about 30 seconds to respond. A result can take one to two minutes to appear.
- A loop of my own making. The takeover check watches sent mail, so the alert email BEC Guard sent to the compliance team was itself flagged as suspicious, and it sent another alert every minute. I had to teach it to recognise its own messages.
- Hosting on a budget. Nebius Serverless and Hugging Face Docker Spaces both turned out to be paid, so I moved to Render. Even then the add-on couldn't connect at first, because Apps Script only allows calls to addresses listed in its manifest.
Accomplishments that we're proud of
- Building a habit, not just a detector. The goal is to put one thought in front of the person paying: verify before paying. That thought leads to one extra step, a phone call to a number from your own records, and that one step is what stops the money from leaving.
- Trustworthy by design. Three independent checks look at the sender, the company and the request, and the request is always compared with the company's own payment history. So even when the sender looks perfect, as with a vendor's real mailbox that's been hacked, the new bank account still stands out. The phone number to call never comes from the email, and every address and number in the model's wording is checked by code before it's shown.
- Hard to fool, and safe when something fails. Models find the facts, but fixed rules make the decision, so text in an email can't talk BEC Guard into "No issues found". If a model call fails, the email isn't skipped: the screening step treats it as a payment request, and the checks against the records still run. The first screening step is backed up by code, so an email that says "this isn't a payment request" still gets checked if it contains bank details.
What we learned
- How these attacks really work. Most come from a lookalike domain, a free email account, or a vendor's real mailbox that's been hacked. The last kind passes every sender check (SPF, DKIM, DMARC), so the only reliable signal is the request itself.
- Verification has to happen outside the attacker's channel. A phone number written in the email is the scam's own number.
- Use the right model for each step. Nemotron Nano screens every email quickly and cheaply. When an email does ask for money or data, the bigger models take over: Super for judgement and the web-search agent, Super VL to read PDF invoices, and Ultra to write the explanation the user reads. That keeps a full check at about a third of a cent per email without giving up quality where it matters.
What's next for BEC-Guard
The hackathon version runs on free tools, which brings a few limits. With the budget for a real product, I would:
- Replace the one-minute check with push events (Gmail Pub/Sub and Microsoft Graph notifications), so BEC Guard reacts within seconds.
- Make it installable for any company: a Google Workspace Marketplace add-on and an Outlook add-in, installed once by an admin. Publishing for other organizations' mailboxes needs Google's review and security assessment (and a paid Azure account for Outlook), which takes weeks and costs money, so it wasn't possible within the hackathon.
- Read admin audit logs on the server to catch sign-ins from new places, and to keep working even if an intruder removes the add-on.
- Sync vendor records from the accounting system (QuickBooks, Xero or NetSuite), and add a payment gate in bill pay that holds payments to a new bank account until someone has called back.
- Move from in-memory state to a database, and host on Nebius Serverless, so it survives restarts and keeps an audit history.
Built With
- claude-code
- dnstwist
- docker
- fastapi
- gmail-api
- google-apps-script
- httpx
- nebius-token-factory
- node.js
- nvidia-nemotron
- openai-sdk
- pydantic
- pypdfium2
- pytest
- python
- rdap
- react
- render
- tailwindcss
- tavily
- typescript
- vite
Log in or sign up for Devpost to join the conversation.