Open the access log of any site you look after and read a few hundred lines. Ask yourself how many of these you can find: a request for backup.sql. A ../etc/passwd. A row of failed password lines.
That is not a breach. That is the reconnaissance phase: automated, untargeted traffic, and it is the prequel to everything a client eventually calls "a hack".
Here is what this article gives you:
- Five patterns worth finding in the logs you already have. They buy you lead time.
- The order to respond in, so your own defenses do not take the client's site down before any attacker gets the chance.
Both are checkable this week. Neither needs a security team.
1. What to look for
Backup hunting. Requests for .sql, .bak, .zip, .dump. Someone is betting a database export was left in the web root. One request is noise. A list of them is a worker going down a checklist.
Path traversal. ../, its encoded variants, /etc/passwd, win.ini. Even one hit is filesystem reconnaissance, not a typo.
Injection probes. union select, information_schema, sleep(. These strings live in attack tooling, not in legitimate application traffic.
Credential attacks. failed password, authentication failure, invalid user, repeated. This is what brute force looks like before anyone is inside.
Webshell and SSRF probes. Upload endpoints tested, metadata endpoints requested. If you see these, stop reading and start investigating.
The value is not forensics. It is lead time. You get to act while it is still noise.
2. How to respond without shooting the client
Watching is safe. Blocking automatically is where small shops hurt the people they look after. The classic failure mode: the firewall takes out the load balancer, the health checker, or the host's own address, and the site goes down. Tools in this space, ours included, have had exactly these bugs. One parser read the version number out of a User-Agent string, Chrome/122.0.0.0, and banned 122.0.0.0, a real address somewhere in the world, not the attacker.
So the order:
- Allowlist first. Load balancers, health checkers, monitoring probes, the host's own public address. If these get banned, the service goes down. Your service, to your client.
- Trusted proxy ranges. Otherwise you ban the reverse proxy instead of the client behind it.
- A ceiling on bans per minute. A burst of blocks is more often a misread log than a crowd of attackers.
- Ban only on confirmed attack evidence: injection, traversal, brute force, webshell, SSRF, credential stuffing. Port scanners and crawlers get an alert, never a firewall rule. Scanning is what the internet does all day. Blocking on it bans innocent crawlers and customers behind shared NAT.
And one week of watching before any blocking does double duty. You learn what is normal for that client, and the allowlist writes itself.
How to run it
One more service in the stack you already deploy. The same stacker.yml that defines the client's application defines the security sidecar: log sources, an alert destination per client, a findings database. Alerts go to email or a webhook, wherever that client's team already talks. The server stays the client's.
If your clients ask where their data lives: MIT-licensed Rust, runs on their server, and the log analysis can run against a local model so log contents never leave the box.
What this will not do
It will not tell you an AI attacked the site. No log line carries that. Good detectors match what the request looks like, not who sent it. And behavior-based ML anomaly detection in this space is roadmap, not shipping. Anyone whose box "uses AI to stop AI attacks" is describing a demo.
Where to start
If you deploy your clients' stacks as code, the security sidecar is one more service in the same file. A stacker.yml is in our open-source stack repository (link below). Standalone install exists too: one-line installer, Docker image.
Watch for a week. Block second.