Real-time fraud detection on e-commerce websites.
FRAID analyzes a URL and returns a 0–100 risk score, an AI-generated explanation in English, and a Chrome extension that intercepts suspicious payments before they are completed.
POST /analyze
{ "url": "https://amazone-flash-deals-292987988976.europe-west2.run.app" }
{
"risk_score": 75,
"risk_level": "HIGH",
"explanation": "This site impersonates the Amazon brand on ephemeral cloud infrastructure. The domain was registered very recently and has high entropy typical of automated phishing campaigns.",
"signals": {
"domain_entropy": 1.0,
"domain_age_days": 0.9,
"tls_cert_age_days": 0.6,
...
}
}Extension Chrome (MV3)
└─ Intercepte les clics de paiement (Payer / Acheter / Commander)
└─ POST /analyze
API FastAPI (api/main.py)
└─ Orchestrateur (api/analyzer.py)
└─ Exécute 7 signaux en parallèle (asyncio.gather)
• domain_entropy
• domain_age_days
• whois_registrar_risk
• tls_cert_age_days
• semantic_similarity
• url_fuzzy_hash_score
• redirect_chain_depth
Fusion du score
└─ Somme pondérée des signaux → score 0–100 → risk_level (LOW / MEDIUM / HIGH)
Explication
└─ LLM (Mistral API ou Ollama) + fallback Python
Données
└─ Qdrant (corpus vectoriel) + corpus de hachages URL phishing
- Docker Desktop
- Ollama with the
mistralmodel - Chrome (for the extension)
git clone <repo>
cd hackathon-project
cp .env.example .env
# Edit .env if needed (see the Configuration section)ollama pull mistral
ollama serve # stays in the backgroundIf Ollama is already running (
address already in use), that’s normal — it’s already up.
docker-compose upCheck that everything works:
curl http://localhost:8000/health
# → {"status":"ok","qdrant":"ok","corpus_size":0}- Ouvrir
chrome://extensions - Enable Developer mode (toggle at the top-right)
- Click Load unpacked
- Select the
extension/folder - The FRAID icon appears in the Chrome toolbar
# Obvious phishing site → should return HIGH
curl -s -X POST http://localhost:8000/analyze \
-H "Content-Type: application/json" \
-d '{"url":"https://amazone-flash-deals-292987988976.europe-west2.run.app"}' \
| python -m json.tool
# Legitimate site → should return LOW (whitelist, score 0)
curl -s -X POST http://localhost:8000/analyze \
-H "Content-Type: application/json" \
-d '{"url":"https://amazon.com"}' \
| python -m json.toolhttp://localhost:8000/test
The page contains 6 payment scenarios (card form, checkout button, order, etc.). Clicking a payment button triggers FRAID interception.
Visit a suspicious site and click a button like Pay / Buy / Order. The extension:
- Intercepte le clic
- Calls
POST /analyzeon the current URL - If
risk_level: HIGH→ shows a blocking modal with the score, AI explanation, and signals - The user can cancel the payment or proceed anyway
Test URL (known phishing):
https://amazone-flash-deals-292987988976.europe-west2.run.app
Root .env file:
# Qdrant (internal Docker service)
QDRANT_URL=http://qdrant:6333
QDRANT_COLLECTION=fraud_sites
# Ollama — access from Docker to the host machine
OLLAMA_BASE_URL=http://host.docker.internal:11434
OLLAMA_MODEL=mistral
# Mistral API (optional — takes priority over Ollama if set)
# MISTRAL_API_KEY=sk-...Without a corpus, the semantic_similarity and url_fuzzy_hash signals return 0 — the other signals compensate. To feed Qdrant with real phishing URLs:
# From the Docker container
docker-compose exec api python ingestion/fetch_feeds.py --limit 500
# Verify
curl http://localhost:8000/health
# → {"corpus_size": 500, ...}| Composant | Technologie |
|---|---|
| API | Python 3.11, FastAPI, uvicorn |
| Signals | httpx, trafilatura, python-whois, tldextract, py-tlsh |
| Embeddings | sentence-transformers (all-MiniLM-L6-v2, CPU) |
| Vector store | Qdrant (Docker) |
| LLM | Ollama (mistral) + Mistral API as fallback |
| Extension | Chrome MV3, vanilla JS, aucun bundler |
| Infra | Docker Compose |
| Tests | pytest, pytest-asyncio, respx (116 tests, 0 network calls) |
pip install -r requirements.txt
pytest tests/ -q
# → 116 passed| Signal | Poids | Description |
|---|---|---|
domain_entropy |
30 % | Shannon entropy + brand impersonation detection |
domain_age_days |
25 % | Recently registered domain = suspicious |
tls_cert_age_days |
15 % | Very recent TLS certificate |
whois_registrar_risk |
10 % | Registrar known for hosting phishing |
semantic_similarity |
10 % | Content similarity vs fraud corpus |
url_fuzzy_hash_score |
5 % | URL similar to a known phishing URL |
redirect_chain_depth |
5 % | Abnormally high number of redirects |
Weights can be overridden via environment variables (W_ENTROPY, W_DOMAIN_AGE, etc.) and are automatically normalized.