Case study 21 / 26
Serverless Log Monitoring & Threat Alert System
A security-focused serverless endpoint that turns raw log lines into incidents, evidence and alerts.
- Status
- Prototype
- Period
- 2025
- Domain
- security · cloud
- Language
- JavaScript
- Last push
- 19 NOV 2025
- License
- None stated
- Source of claims
- api/detect.js, package.json
One API-key-protected serverless function receives log events, matches them against detection rules, records incidents and raw evidence in Supabase, tracks failed logins per IP in five-minute windows, and pushes critical findings and brute-force bursts to a Discord or Slack webhook.
01/The problem
Small services produce logs that nobody watches. A full SIEM is overkill, but obvious hostile patterns — credential stuffing, SQL injection probes, scanner traffic — should still raise an alarm. The goal: a detection pipeline that costs nothing when idle and deploys as a single function.
02/The system
One API-key-protected serverless function receives log events, matches them against detection rules, records incidents and raw evidence in Supabase, tracks failed logins per IP in five-minute windows, and pushes critical findings and brute-force bursts to a Discord or Slack webhook.
- Log source to POST /api/detect
- POST /api/detect to Rule engine
- Rule engine to Incidents
- Rule engine to Evidence
- Rule engine to Counters
- Counters to Brute force
- Incidents to Webhook
- Brute force to Webhook
03/Implementation
- 01POST /api/detect accepts a JSON payload or a raw string; any other method returns 405.
- 02Requests are rejected with 401 unless the x-api-key header matches a server-side secret.
- 03Four regex rules classify each line: failed-login (medium), admin-access (high), sql-injection (critical), and suspicious-user-agent for scanners such as sqlmap, nikto and nmap (medium).
- 04Matching events become incidents in a Supabase `incidents` table with an 800-character excerpt, the matched rules and metadata.
- 05The raw message is uploaded to a Supabase Storage evidence bucket under the incident ID.
- 06Failed logins increment a per-IP counter keyed by five-minute window; three or more create a separate brute-force incident.
- 07Critical findings and brute-force bursts are posted to a configurable Discord/Slack webhook.
04/Engineering
Store signal, not noise
Clean events return 200 with an empty findings list and are never written. Storage and alerting cost scale with threats, not traffic.
Fail soft around detection
Evidence upload, counter updates and webhook delivery log a warning and continue. A storage hiccup never stops an incident from being returned to the caller.
Source attribution order
The source IP is taken from the log line itself first, then x-forwarded-for, then a custom x-source header, then the socket — so forwarded logs are attributed to the original actor, not the shipper.
Privileged client stays server-side
The Supabase service-role client runs only inside the function, with session persistence disabled; credentials are read from Vercel environment variables.
05/Interface
No product screenshots are published for this project. The visual above is a code-driven representation of how it behaves, built from the repository source — not a screenshot.
06/Tech stack
- JavaScript
- Node.js
- Vercel Functions
- Supabase
- PostgreSQL
- Supabase Storage
- Webhooks
07/Result
Verified outcomes
- Deployed as a Vercel serverless function backed by Supabase.
- End-to-end path from log line to stored incident, evidence file and webhook alert within a single request.
Known limitations
- Detection is regex-based and intentionally simple — it flags obvious patterns, not novel attacks.
- Counter updates are read-then-write, so concurrent bursts can under-count.
08/Links
Next case study
Animation Ad →