Inspiration
Cash-on-delivery and chat-based scams are one of the most common ,and most underserved , trust & safety problems in social commerce. A buyer messages a seller, gets pressured into paying "a small unlock fee" via WhatsApp, and by the time anyone notices, the platform's only response is a silent takedown with no explanation. That opacity bothered us: users who get flagged (correctly or not) have no way to understand why, and trust & safety teams reviewing edge cases have no way to audit the decision either.
We wanted to build something that treats explainability as a first-class feature, not an afterthought bolted onto a model after the fact.
What it does
ScamShield scores any buyer/seller chat message from 0–100 for scam risk, and shows exactly which signals triggered that score, in plain language , off-platform payment requests, urgency/pressure tactics, prize scams, phishing links, advance-fee requests, credential/OTP phishing, unrealistic pricing, and scripted-message grammar patterns. A message isn't just labeled "high risk" — it comes back with a readable list like "Requests payment or contact outside the platform (+35)" and "Asks for an upfront fee, deposit, or 'unlock' payment (+30)".
How we built it
We built the detection logic as a pure, framework-agnostic, rule-weighted heuristic engine , deliberately not a trained ML classifier , so it works correctly from message one with zero training data, is fully deterministic, and can be reviewed and version-controlled the same way a trust & safety team would review a policy document.
The backend is built on NestJS, structured as a dedicated feature module
(ScamModule) with a controller, service, and DTO-based request validation via
class-validator. The frontend is a single-file vanilla HTML/CSS/JS page with no build step,
served directly by Nest's static file module. We deliberately kept the engine itself free of
any Nest imports, so it's independently unit-testable and portable to any Node backend.
Challenges we ran into
Most of our real challenges were toolchain problems, not algorithm problems:
- Silent build failures on Windows.
nest buildreported zero errors but never produceddist/main.js, which madenest startcrash with a confusingMODULE_NOT_FOUNDon a file that should have existed. We eventually traced it back to a folder-structure mismatch , the scaffolded files had ended up flat in the project root instead of nested undersrc/andsrc/scam/, so Nest's compiler had nothing to actually find at the configured source root. - ESM-first NestJS scaffolding. The current Nest CLI generates an ESM project by default
(
"type": "module"inpackage.json), which meant__dirnamewasn't available for static file path resolution and every relative import needed an explicit.jsextension even in.tssource files , an easy thing to trip over if you're used to older CommonJS-style Nest projects. - Time pressure. With a hard 72-hour (and for us, an even tighter last-mile) deadline, we had to be disciplined about scope , a transparent rule engine we could ship and demo reliably beat a more "impressive" ML model we might not have finished testing in time.
Accomplishments that we're proud of
Getting from a cold start to a fully working, explainable, end-to-end scam detector , API, validation, frontend, and a real demoable UI , with zero external dependencies at inference time, all while diagnosing and fixing a genuinely confusing Windows build issue under serious time pressure.
What we learned
That explainability doesn't have to mean sacrificing simplicity or speed , a well-designed rule-weighted system can be both instant and auditable, which matters a lot for trust & safety tooling where false positives have real consequences for real sellers and buyers. We also came away with a much sharper understanding of how NestJS's newer ESM-based tooling changes some long-held assumptions about project structure and imports.
What's next for ScamShield
- Blend the heuristic score with a lightweight ML classifier to catch messages that evade keyword rules , obfuscated spelling, non-English scam scripts.
- Add per-seller/per-buyer risk aggregation over message history, not just single-message scoring.
- Build a moderation dashboard for human review of high/critical flags, with a one-click appeal path for the user being flagged.
- Expand the rule set to be multilingual ,the current version is English-only.
Built With
- class-validator
- css3
- express.js
- html5
- javascript
- nestjs
- node.js
- rest-api
- typescript


Log in or sign up for Devpost to join the conversation.