尚未收集儲存庫資訊。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
Is this link safe? Verifiko detects phishing and malware URLs and returns an explainable verdict in seconds — a FastAPI + React app with a developer API. Live at verifiko.es
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗English · Español
Is this link safe? Verifiko detects phishing and malware links. You paste a URL and get an explainable verdict in seconds. The same engine is available to developers through a versioned REST API. It is built as a direct alternative to tools like URLert.
Live: https://www.verifiko.es · API: https://api.verifiko.es/api/v1 (reference)
| Landing | Verdict |
|---|---|
Each verification produces a trust score (0–100), a risk level (SAFE → CRITICAL) and
the list of signals that led to it. Every signal has a severity, a confidence and an EN/ES
explanation, so the verdict can be audited instead of trusted blindly.
Detection engine
paypa1.com, g00gle.com) detected through leetspeak normalization plus
edit distance.HIGH/CRITICAL.Product and API
/api/v1 surface, with per-plan daily quotas and
burst rate limits.POST /scans (or /scans/batch) → 202, then poll GET /scans/{id} or
receive a signed webhook. Jobs live in Postgres. Dispatch runs either in-process or through a
queue (Upstash QStash) for serverless runtimes.Roadmap (not built yet)
Browser (React SPA) API clients (X-API-Key)
www.verifiko.es │
└───────────────┬──────────────────┘
▼
FastAPI · /api/v1 · api.verifiko.es
┌──────────────────────────────────────────────────────────┐
│ entrypoints routes, schemas, DI container │
│ application use cases, signal analyzers, ports │
│ domain entities, scoring policy, compound rules │
│ infrastructure adapters behind the ports ↓ │
└──────────────────────────────────────────────────────────┘
Postgres (Neon) Redis (Upstash) URLhaus · OpenPhish · RDAP
SQLAlchemy + limiters, caches HTML / TLS / DNS fetchers
Alembic (SSRF-guarded, IP-pinned)
Browserless · Cloudflare R2 · Resend · QStash (optional)
api/): Python 3.11, FastAPI, and Clean Architecture with strict layering.
The domain does no I/O. Application code depends only on ports. Infrastructure adapters are wired
in one dependency-injection container (app/entrypoints/api/dependencies/container.py).
Postgres is reached through SQLAlchemy and psycopg v3, with Alembic migrations.web/): React 18, TypeScript and Vite, with React Router and EN/ES i18n. The
landing is server-rendered at build time (prerendered). PWA support (service worker + install
prompt) is behind a build flag.api/index.py) and the static frontend. Schema
migrations run from a GitHub Action whenever a migration lands on main, separately from the
code deploy (see api/DEPLOY.md).Risky capabilities ship behind feature flags that are off by default: deep scan, screenshot storage, the fail-fast path, the OpenPhish feed and queue dispatch. New capabilities therefore land dark until they are explicitly enabled.
http/https, rejects
internal hostnames, resolves DNS, and blocks the request unless every resolved address is
globally routable. That includes IPv4 addresses embedded in IPv6: IPv4-mapped, 6to4, Teredo,
NAT64 and IPv4-compatible. Adapters then connect only to the validated, pinned IP, which closes
DNS-rebinding/TOCTOU and redirect-follow bypasses.timestamp.body, sent as X-Verifiko-Signature. See
verification.X-Forwarded-For only when the request arrives from a
configured trusted proxy.Requirements: Python 3.11, Node.js 18+, and Docker (for the local Postgres).
API
cd api
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env # local-dev defaults; every variable is documented inline
docker compose up -d db
alembic upgrade head
uvicorn app.entrypoints.api.main:app --reload --port 8000
api/.env.example lists every setting by name. Without extra configuration you get a working
local API using Postgres only. Redis, Google Sign-In (GOOGLE_CLIENT_ID), email
(RESEND_API_KEY), deep scan (DETONATION_ENABLED, BROWSERLESS_ENDPOINT) and screenshot storage
(SCREENSHOT_STORAGE_ENABLED, R2_*) are optional. In production AUTH_TOKEN_SECRET and
SCAN_WEBHOOK_SIGNING_SECRET are required.
Web
cd web
npm ci
npm run dev # http://localhost:5173, talks to http://localhost:8000
In development the app targets http://localhost:8000 when VITE_API_BASE_URL is unset. Copy
web/.env.example to .env only if you need to set VITE_GOOGLE_CLIENT_ID, and in that case
set VITE_API_BASE_URL=http://localhost:8000 too.
cd api
python -m pytest -q # ~500 unit + integration tests
python -m evaluation.run_evaluation # detection-quality harness
The evaluation harness scores the engine offline against a labeled corpus of malicious and benign
URLs. At the MEDIUM threshold the current baseline is precision 1.00, recall 0.82, false
positive rate 0.00. Changes must not regress precision.
Frontend:
cd web
npm run test # Vitest + Testing Library (jsdom)
npm run build # type-checks (tsc --noEmit), builds and prerenders
Unit tests live next to the code they cover (src/**/*.test.{ts,tsx}). CI runs lint, tests and
the build for both the API and the web app on every pull request (see the badge above), with the
detection evaluation harness as a regression gate.
The web app is also tested by hand in a real browser before and after each change, across viewports, both languages and the PWA. The process is described in docs/QA.md.
Behavior changes go through OpenSpec. Each one starts as
a proposal with a spec delta, design and tasks under openspec/changes/, and once merged it is
archived into living capability specs under openspec/specs/. Examples include
the outbound fetch guard and the production config safety rules. Pure refactors, docs and
dependency hygiene skip it.
api/ FastAPI service (app/{domain,application,infrastructure,entrypoints}), tests, evaluation
web/ React + Vite + TypeScript app
docs/ API reference and design docs (headless detonation, R2 screenshots, PWA)
openspec/ Capability specs and archived change proposals
screenshots/ Images used in this README
Apache License 2.0 © 2026 Hernán Bonavota