Risk-first scam triage for forwarded messages, links, screenshots, and documents.
TrustBot started as a small heuristic API for answering a practical question:
"I got this forwarded on chat. Should I trust it?"
The project now has two layers:
v1: a simple single-pass analyzerv2: an investigation-oriented API that stores artifacts, collects structured evidence, and supports multi-turn follow-up
Most suspicious forwards are incomplete:
- cropped screenshots
- shortened links
- partial copied text
- messages missing sender context
That makes scam detection a poor fit for a one-shot "safe or unsafe" classifier.
TrustBot is intentionally opinionated:
- it is risk-first
- it treats "safe" as rare
- it prefers asking for one precise follow-up artifact over bluffing confidence
/v1/analyze routes a single artifact through heuristic pipelines and returns:
RISKYUNSURESAFE(rare)
This is the original MVP surface.
/v2/investigations/* treats analysis as an investigation:
- create or continue a case
- store artifacts
- collect evidence from providers
- aggregate weighted evidence
- return
RISKY,NEED_MORE, orLIKELY_SAFE
This is the new direction for the project.
- text forwards
- links
- screenshots/images
- PDFs and image-like documents
- small context notes added by the user in V2
TrustBot is designed around a few product rules:
- Strong scam signals should dominate weak neutral signals.
LIKELY_SAFEshould require positive evidence, not merely absence of red flags.- If confidence is low, the response should request one next-best artifact.
- User-facing explanations should be plain-language and operational.
- scam-text pattern matching for urgency, OTP, KYC, payment, and callback lures
- URL static checks for shorteners, IP literals, no TLS, punycode, and suspicious TLDs
- URL provenance checks via redirect following and shallow landing-page inspection
- image quality heuristics for compression and low-signal screenshots
- document text extraction and optional OCR-backed text analysis
- first-class investigations
- first-class artifacts
- structured evidence items
- weighted decision engine
- multi-turn artifact continuation
- heuristic impersonation checks
- heuristic domain reputation hints
- SQLite-backed persistence for local development
TrustBot is an independent research/evaluation project and is not affiliated with, endorsed by, or sponsored by WhatsApp or Meta.
"WhatsApp" is used descriptively to indicate the intended workflow of forwarding suspicious content for verification.
No warranties are provided. Use at your own risk.
- Python 3.10+
- Windows PowerShell examples are shown below, but the app is plain Python/FastAPI
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe -m uvicorn app.main:app --reloadServer:
http://127.0.0.1:8000
Docs:
http://127.0.0.1:8000/docs
If you want OCR for screenshots or documents when plain extraction is insufficient:
.\.venv\Scripts\python.exe -m pip install -r requirements-ocr.txtNotes:
- you may need to install Tesseract OCR separately
- if OCR is unavailable, TrustBot degrades toward uncertainty rather than pretending confidence
POST /v1/analyze
POST /v2/investigations/analyzeGET /v2/investigations/{investigation_id}POST /v2/investigations/{investigation_id}/artifacts
curl -X POST http://127.0.0.1:8000/v1/analyze `
-H "Content-Type: application/json" `
-d '{ "content_type":"text", "text":"URGENT: Your KYC is pending. Click https://bit.ly/verify-kyc and share OTP to avoid account block." }'curl -X POST http://127.0.0.1:8000/v1/analyze `
-H "Content-Type: application/json" `
-d '{ "content_type":"link", "url":"http://bit.ly/otp-reset" }'curl -X POST http://127.0.0.1:8000/v1/analyze `
-H "Content-Type: application/json" `
-d '{ "content_type":"text", "text":"Your bill is generated. Please pay by due date." }'.\.venv\Scripts\python.exe tools\demo_local.py --image .\samples\some_screenshot.png
.\.venv\Scripts\python.exe tools\demo_local.py --file .\samples\some_notice.pdfStart an investigation:
.\.venv\Scripts\python.exe tools\demo_v2.py --text "URGENT: Your KYC is pending. Click https://bit.ly/verify-kyc and share OTP now."Continue an investigation:
.\.venv\Scripts\python.exe tools\demo_v2.py --investigation-id inv_123 --type context --text "This came from a forwarded group and claims to be from my bank."Fetch an investigation:
.\.venv\Scripts\python.exe tools\demo_v2.py --investigation-id inv_123 --getcurl -X POST http://127.0.0.1:8000/v2/investigations/analyze `
-H "Content-Type: application/json" `
-d '{ "artifact": { "type":"text", "text":"URGENT: Your KYC is pending. Share OTP now." }, "locale":"en_IN", "channel":"whatsapp" }'Example response:
{
"investigation_id": "inv_123",
"status": "RESOLVED",
"verdict": "RISKY",
"confidence": 0.63,
"headline": "This looks like a likely OTP scam.",
"reasons": [
"Asks for an OTP — a common scam pattern.",
"Uses urgent/threatening language designed to rush you."
],
"recommended_action": "Do not click links, share OTPs, send money, or call numbers from the message. Verify through an official channel you open yourself.",
"next_best_artifact": null,
"artifacts_seen": 1,
"trace": {
"risk_score": 0.775,
"trust_score": 0.0,
"quality_penalty": 0.0,
"coverage_score": 0.25,
"contradiction_score": 0.0
}
}curl -X POST http://127.0.0.1:8000/v2/investigations/inv_123/artifacts `
-H "Content-Type: application/json" `
-d '{ "artifact": { "type":"context", "text":"This came from a forwarded family group and claims to be from my bank." } }'curl http://127.0.0.1:8000/v2/investigations/inv_123RISKY: strong scam signals foundUNSURE: not enough evidenceSAFE: low-risk with better-than-neutral evidence, but still not a guarantee
RISKY: strong risk evidence existsNEED_MORE: current artifacts are insufficient or low qualityLIKELY_SAFE: positive evidence supports legitimacy, with low contradiction
V1 is intentionally small:
- route request by content type
- run relevant pipelines
- fuse heuristic signals
- return verdict and next step
Core files:
app/main.pyapp/router.pyapp/fusion.pyapp/evidence.pyapp/pipelines/
V2 separates concerns more explicitly:
app/api/for FastAPI routesapp/domain/for models, enums, and decisioningapp/providers/for evidence collectorsapp/services/for orchestrationapp/repositories/for persistenceapp/schemas/for request/response models
The full V2 design rationale is documented in:
V2_ARCHITECTURE.mdCHANGELOG.md
app/
api/ # v2 routes
domain/ # v2 enums, models, decision engine
pipelines/ # v1 heuristic analyzers reused by v2 providers
providers/ # v2 evidence collectors
repositories/ # SQLite-backed local persistence for v2
schemas/ # v2 API request/response models
services/ # v2 orchestration services
evidence.py # v1 evidence-request logic
fusion.py # v1 signal fusion
main.py # FastAPI app entrypoint
models.py # v1 request/response models
router.py # v1 routing/orchestration
storage.py # v1 ephemeral storage helpers
tools/
demo_local.py # helper script for local image/document analysis
demo_v2.py # helper script for creating/continuing v2 investigations
samples/ # sample inputs
V2_ARCHITECTURE.md
README.md
V2 uses SQLite by default for local development.
- default DB path:
trustbot_v2.db - override with:
TRUSTBOT_DB_PATH
Example:
$env:TRUSTBOT_DB_PATH = "data\trustbot_v2.db"
.\.venv\Scripts\python.exe -m uvicorn app.main:app --reload- V1 and current V2 are still heuristic-first, not evaluation-calibrated
- V2 domain reputation is intentionally lightweight today
- impersonation detection is rule-based, not model-backed
- V2 does not yet auto-promote URLs extracted from text into linked child artifacts
- OCR quality depends on the environment and Tesseract availability
- there is not yet a formal benchmark dataset committed in-repo
- add URL extraction into linked V2 artifacts
- add a regression/evaluation harness with labeled cases
- strengthen impersonation and brand/domain consistency checks
- improve response composition for richer plain-language explanations
- add a simple UI or CLI flow for multi-turn investigations
Install dependencies and run the V2 regression suite:
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe -m pytestCurrent regression coverage focuses on:
- obvious OTP scam text resolving as
RISKY - URL extraction from text into derived V2 link artifacts
- low-signal image input resolving as
NEED_MORE - brand/domain mismatch links resolving as
RISKY - fixture-driven golden cases in
tests/fixtures/v2_cases.json
MIT