Try it

Inspiration: the problem

International students in the US are a favourite target of impersonation scams. The FBI's Internet Crime Complaint Center published a public service announcement in September 2026 about criminals impersonating US and foreign law enforcement and government officials, naming international students among the targets, and earlier ones about fake "Chinese police" and about scammers threatening students on valid visas with deportation. University international offices (Rutgers, UC Berkeley, Ohio State, CSUN and others) all carry the same warning: a caller claims to be USCIS, ICE or the police, says your SEVIS record or visa is about to be cancelled, demands a fee in gift cards or crypto, and tells you not to tell your school.

These scams work because of the moment they create. A student far from home, worried about their status, gets a message that says act now and tell no one. The advice "contact the agency through official channels" exists, but it is scattered across agency pages, and it is hardest to remember at exactly the moment you need it. Pasting the message into a search engine or a chatbot means sending a message that may contain your name, case details or a link to someone else's server.

I wanted something you can use in that moment: paste the message, see clearly which parts are red flags and why, see where a link really goes, and get one safe next step, without anything leaving your phone.

What it does

Second Read is a web app. You paste a text, email or chat message, plus the sender and any link if you have them. Using fixed, readable rules (no AI service, no network calls), it:

  • Highlights each warning sign in the message itself, numbered and coded by strength: threats of arrest or deportation, secrecy or "stay on the line", unusual payment (gift cards, crypto, crypto ATMs, wires, payment apps), requests for codes, passwords or SSNs, time pressure, "pay a fee to get your package / job / refund", moving you to WhatsApp or a number in the message, and claims to be an agency, police, embassy, school, bank or well-known company.
  • Explains each sign in plain language and links to the public FTC, FBI IC3, USCIS, IRS, SEVP or university guidance it comes from.
  • Takes every link and the sender address apart without opening them: the real registrable domain (using the Public Suffix List), decoded punycode with impostor characters highlighted, lookalike and typo-squatted brand names (paypa1, rnicrosoft, a Cyrillic "а" in "аpple.com"), brand names inside unrelated domains (usps-parcel-care.top), decoy subdomains (amazon.com.order-hold.info), URL shorteners, @ tricks, raw IP addresses and links hidden inside other links.
  • Checks the claimed sender against the real domains: "USPS" linking somewhere USPS does not own, a "government" message without a .gov address, a "university office" without a .edu address, an "agency" writing from Gmail.
  • Gives a calibrated verdict that never says "safe": Several strong warning signs, Some warning signs, A few weak signs, or No known warning signs found: that does not mean it is safe. A sender whose address really matches the organisation lowers the weight of pressure words, but never removes money, secrecy or lookalike signs.
  • Suggests safe next steps for the situation: check through a channel you find yourself, tell your international student office, how USCIS and SEVP actually collect fees, how to track a package yourself, how to report (FTC, IC3, forwarding scam texts to 7726), and what to do if you already paid, clicked or shared a code, by payment type.
  • Recognises a small set of Simplified Chinese phrases used in fake "Chinese police" and embassy calls.

Intended users

International university students in the US (F-1 and J-1), and the friends, roommates and international-office staff who help them check a message. The design assumes a stressed person on a phone: one box, one button, plain words, big verdict, and the first next step visible without hunting.

One example of the safer outcome

Synthetic example. Lin, a fictional first-year F-1 student, gets a voicemail: an "officer" from U.S. Citizenship and Immigration Services says her SEVIS record will be terminated today, a warrant will be issued unless she pays a $950 "correction fee" in Target gift cards, and she must not discuss it with her school.

  • Without Second Read: scared and told to keep it secret, her likely next step is to buy the gift cards, which is exactly what the FBI and FTC describe victims doing.
  • With Second Read: she pastes the transcript and sees "Several strong warning signs". The threat ("SEVIS record will be terminated", "warrant", "arrest"), the secrecy demand, the gift-card payment, the fee and the call-back number are all highlighted, and a note says that an official-sounding caller plus pressure to pay and keep quiet is the exact pattern in the FBI and FTC impersonation warnings. The first steps it suggests are to check through a channel she finds herself and to tell her international student office using the contact details on her school's website, noting that USCIS fees go through a myUSCIS account and SEVP does not phone students to collect fees. She hangs up and calls her DSO instead of paying.

How we built it

  • Plain HTML, CSS and JavaScript modules, no framework and no runtime dependencies, hosted on GitHub Pages. A service worker makes it work offline after the first visit.
  • Rules as data: each warning sign has readable regular expressions, a strength tier, an explanation and its sources. Negated phrasing ("we will never ask for your code", "call the number on the back of your card") is detected so real bank and two-step messages are not flagged.
  • Link anatomy with our own Public Suffix List lookup (wildcards, exceptions, the private section) and RFC 3492 punycode decoder, checked against the PSL project's official test vectors, and a subset of the Unicode UTS #39 confusables table for lookalike characters.
  • A hand-compiled organisation table (USCIS, ICE/SEVP, IRS, SSA, State Department, FBI, USPS, couriers, banks, payment apps, login providers...) with the domains each really uses.
  • Trust as a testable property: a strict Content Security Policy (connect-src 'none', form-action 'none'), no storage, fields cleared on leave, spell-check and Grammarly disabled in the inputs, user text rendered only with textContent, and user links never clickable.
  • Testing: 17 unit tests (including 78 PSL test vectors) and 11 Playwright browser tests run against both the local build and the live site. They cover zero network requests during a check (with a pasted marker string), the CSP actually blocking fetch, XHR and external images, no cookies or storage, offline use, error handling, phone-width layout, and axe-core accessibility checks in light and dark mode.
  • Evidence on held-out synthetic messages, described below.

Evidence: how well does it work?

I measured the rules on labelled synthetic messages modelled on the cited advisories. "Flagged" means a verdict of Some or Several strong warning signs. To avoid grading my own homework, the held-out sets were written by separate AI sessions that could not see the rules, and each was frozen in git before the rules were run on it once.

  • v1 rules, held-out set 1 (30 scam, 25 legitimate), independent: flagged 24 / 30 scams; false alarms on 0 / 25 legitimate messages.
  • v2 rules, held-out set 2 (30 scam, 30 legitimate, 12 deliberately tricky), independent: flagged 22 / 30 scams; false alarms on 4 / 30.
  • v3 rules (current), held-out set 2 after fixing what it revealed, not independent: flagged 28 / 30 scams; false alarms on 2 / 30.

On messages it had never seen, it flagged roughly three to four in five scams, with between 0 and 4 false alarms out of 25–30 legitimate look-alikes. In scam messages, it found 80 of the 103 individual warning signs the labeller marked (v2, held-out 2). The current version has no independent measurement: a third held-out set was planned but its generation was blocked by an automated safety filter, so I report that gap rather than a number. These are small synthetic sets, not a real-world detection rate. Every per-message result is in the repository.

Challenges we ran into

  • Real messages use scam words too. A bank's genuine fraud alert says "verify", a two-step text contains a code, a school reminder has a deadline and mentions SEVIS. Handling negation ("never share this code"), "call the number on the back of your card", and letting a matching sender domain soften pressure words (but never money or secrecy signs) took most of the tuning.
  • Making the lookalike visible. The first version showed the decoded domain "аpple.com" in bold as the "real website", which looked exactly like Apple and almost endorsed it. Now each impostor character is highlighted and named ("Cyrillic а, U+0430, not the Latin a it looks like").
  • Honest evaluation. It is easy to tune rules until a test set passes. Writing the held-out sets independently, freezing them before running, and reporting the independent numbers separately from the after-the-fact ones kept me honest, including the lower 73% result.
  • Proving privacy rather than promising it. A static page can still leak through fetch, images, spell-check services or extensions. The CSP, the tests that try to send data and check it is blocked, and the in-page request counter make the claim checkable.

Accomplishments that we're proud of

  • A verdict that never says "safe", and explains its own uncertainty.
  • Link anatomy that exposes punycode homographs, decoy subdomains and brand-in-domain tricks without ever opening a link.
  • Every warning sign traces back to a public FTC, FBI, agency or university source.
  • Privacy that is verified by automated tests on the live site, not just stated.
  • An evaluation that reports misses and false alarms on data the rules had never seen.

What we learned

  • The most useful output is not the verdict but the next step. "Call your international student office using the number on your school's website" is the action that actually breaks the scam.
  • Calibration matters as much as detection. A tool that cries wolf at every real deadline teaches people to ignore it.
  • Domain logic is subtle: "the real website" is the registrable domain, which needs the Public Suffix List (think github.io or gov.cn), and a .edu ending is meaningless if the letters before it are Cyrillic.

A limitation

Second Read only knows a fixed set of rules. On the independent test it missed polite scams with no money mentioned yet (a "wrong number" opener that moves to WhatsApp), a Chinese-language "customs seized a parcel in your name" text, and a sublet holding fee for a room the poster "can't show". It also over-flags messages that quote scam wording, such as a friend warning you about fake embassy calls. It cannot verify who really sent a message, cannot see images, QR codes or calls, and never opens links, so it cannot know where a short link leads. That is why its lowest verdict says "no known warning signs found", never "safe". It is a prototype checking aid, not a guarantee and not an emergency service: if you are in danger, call 911.

What's next

  • Testing with real international students and an international student office (none has happened yet), especially on wording and on which next step people actually take.
  • More languages used by international students (Korean, Hindi, Arabic, Spanish), written with native speakers.
  • Letting a school add its own domains and payment vendors in a shareable config file.
  • A share-target so you can send a message to Second Read from your phone's share menu without copy-pasting.

Credits, pre-existing work and AI assistance

  • Public Suffix List (Mozilla Public License 2.0), Unicode confusables data (Unicode License v3), PSL test vectors (CC0).
  • Development tools only: Playwright (Apache-2.0), axe-core (MPL-2.0), Node.js, FFmpeg for the demo video.
  • Advice and warning signs paraphrase public guidance from the FTC, FBI IC3, USCIS, IRS, DHS SEVP, get.gov, the Embassy of the PRC in the US, and the Rutgers, UC Berkeley, Ohio State and CSUN international offices.
  • No other pre-existing code, templates or assets were used.
  • Built with an AI coding assistant (Claude); design decisions, testing and write-up reviewed by the author. The synthetic held-out test messages were generated by separate AI sessions that could not see the rules.

Built during the event

All project work (code, rules, data processing, tests, screenshots, video and this write-up) was created during SafeSpace Hacks, October 17 – November 22, 2026, starting October 24, 2026.

Built With

Share this project:

Updates

Submission history