Phishing & threat-analysis platform
Documentation: https://thalesgroup-cert.github.io/suspicious/
Suspicious inspects, classifies, and reports suspicious emails, files, URLs, IPs, and file hashes. Submit an item from the web UI or forward an email to a monitored mailbox; Suspicious runs it through YARA rules, a sandbox, metadata checks, and a machine-learning email classifier, then returns a scored verdict and a full report.
Built and maintained by the Thales Group CERT.
Watch the full walkthrough with subtitles (about 100 seconds), or open the MP4 directly. The video is generated by a Playwright script, so it stays in step with the UI: see Product demo. Page-by-page clips are in the Product tour below.
- Analyzes emails (
.eml,.msg), documents, archives, executables, URLs, IP addresses, and file hashes. - Scores each submission as Safe, Inconclusive, Suspicious, or Dangerous.
- Reports results through a web UI with dashboards, per-analyzer output, and submission history.
- Ingests email automatically from IMAP/IMAPS mailboxes.
- Notifies reporters of the outcome by email.
- Integrates with Cortex, TheHive, MISP, LDAP, Elasticsearch, ChromaDB, and S3-compatible storage.
Requires Docker and Docker Compose v2.
git clone https://github.com/thalesgroup-cert/suspicious.git
cd suspicious
# Example configs that run as-is for local development
cp docs/getting-started/examples/deployment-env.example deployment/.env
cp docs/getting-started/examples/Suspicious-settings.example.json Suspicious/settings.json
cd deployment
docker network create suspicious_net
docker compose build suspicious
docker compose up -d db_suspicious redis_cache redis_broker
docker compose up -d --no-deps suspicious
make migrate
make seed-config
make createsuperuserOpen http://localhost:9020/admin/ and sign in.
The example configs use throwaway local credentials. Change every secret before exposing the app. Full guide, the complete stack (UI, HTTPS, Cortex), and configuration reference: INSTALL.md and CONFIG.md.
Three files hold all configuration. Templates ship in the repo.
| File | Purpose |
|---|---|
deployment/.env |
Image versions, ports, paths, database and storage credentials |
Suspicious/settings.json |
Django settings, integrations, branding, SMTP, allowed domains |
email-feeder/config.json |
IMAP/IMAPS mailboxes, S3 storage, polling interval |
See CONFIG.md for every parameter.
| Component | Role |
|---|---|
| Django REST API | Submission, analysis orchestration, reports. Gunicorn on port 9020. |
| React UI (React 19, Vite, MUI) | Frontend served by Nginx on port 9021. |
| Celery worker + beat | Background jobs: case finalisation, Cortex sync, stale-job rescue, KPI snapshots. |
| MariaDB | Metadata, results, KPIs. Holds the CaseAnalyzerJob ledger behind the Cortex webhook lookup. |
| Valkey / Redis | Celery broker and Django cache. |
| Elasticsearch | Search and indexing. |
| Cortex | Analyzer engine — YARA, AI, sandbox, metadata, FileInfo. Reports back via an HMAC-signed webhook. |
| ChromaDB | Vector store for semantic similarity against past cases. |
| RustFS (S3-compatible) | Stores uploads, attachments, artifacts. |
| Email Feeder | Polls IMAP/IMAPS mailboxes and imports emails. Runs as a non-root user. |
| Traefik | Reverse proxy and TLS termination. |
| Vault | Production secret storage. |
- Django creates a
Case. For each analyzer it writes anAnalyzerReportand aCaseAnalyzerJobrow in one transaction, pinning the(case, cortex job)mapping at dispatch. - Cortex runs each analyzer and posts to the HMAC-signed webhook on completion.
- The webhook looks up the case in
CaseAnalyzerJob, then enqueues a Celery task that takes a per-case lock, updates the job, and callsfinalise_caseonce the case has no pending jobs left. finalise_casescores the case, pushes to TheHive/MISP if configured, queries ChromaDB for similar past cases, and emails the reporter.- Celery beat re-checks any webhook the platform missed (every 300 s) and fails
jobs stuck past
STALE_JOB_TIMEOUT_SECONDS(every 600 s), so cases never stall.
Analyzers/AIMailAnalyzer classifies emails by intent (phishing, malicious,
suspicious, benign) using a Sentence-Transformers embedding model and a custom
classifier, with ChromaDB for similarity search. It runs as a Cortex analyzer
alongside the static rules.
To train it on your own data:
- Open
Analyzers/AIMailAnalyzer/for the training scripts. - Prepare a labeled dataset (legitimate vs phishing).
- Train the model.
- Deploy it in Cortex with the other analyzers.
- Review precision and false-positive rates; retrain as needed.
Use it alongside YARA, sandbox, and metadata analyzers. Do not auto-block on the classifier alone.
See CONTRIBUTING.md for coding standards and the pull request flow.
git checkout -b feature/your-feature
# make changes, commit, push
# open a pull requestBug reports and ideas are welcome in issues.
Short clips of each page, recorded from the real UI with fictional data. The same clips, with more context, are in the UI tour.
GitHub Actions runs six workflows plus Dependabot under .github/.
| Workflow | Trigger | Runs |
|---|---|---|
ci.yml |
PRs and pushes to main/test |
commit-lint, ruff, migration-drift check, Django tests, feeder tests, frontend (eslint + tsc + vitest + build), image builds |
e2e-deploy.yml |
PRs, pushes to main/feature/frontweb |
full-stack deploy smoke test against a stubbed Cortex |
docs.yml |
PRs and pushes to main |
builds the MkDocs site and deploys it to GitHub Pages |
release.yml |
pushes to main/test, v* tags |
builds and pushes images to GHCR with SBOM and provenance |
codeql.yml |
PRs, pushes to main, weekly |
CodeQL for Python and JS/TS |
security.yml |
PRs, weekly | Trivy, gitleaks, pip-audit, pnpm audit |
| Component | Image |
|---|---|
| Django API | ghcr.io/thalesgroup-cert/suspicious |
| Frontend | ghcr.io/thalesgroup-cert/suspicious-ui |
| Email feeder | ghcr.io/thalesgroup-cert/suspicious-feeder |
Deployment is manual via deployment/Makefile (make deploy); CI never holds
production credentials.
Released under the Apache License, Version 2.0. See LICENSE.
Questions, ideas, or bugs: open an issue.









