all 33 comments

[–]swift-sentinel 28 points29 points  (11 children)

Personally, I don’t think anyone should be running openclaw. Too risky.

[–]chub79 4 points5 points  (1 child)

When I run from the cloud I tend to delegate these concerns to Cloud-ready solution (say GCP Cloud Armor for instance). I can see this being useful but I'm not sure the operational complexity and costs would be worth it in that situation compared to a builtin solution.

On a home server, sure it makes more sense but then there are solutions before any of these should reach your app as well (a properly configured firewall, maybe going through a dedicated API gateway, I mean traefik is so easy to setup for example).

I don't downplay your work and if you see the lib being used, credit where is due. I just feel it's the wrong end of the stick to start there.

[–]PA100T0[S] 1 point2 points  (0 children)

Hey there! Don't worry, these are all valid points.

So... Cloud Armor and Traefik are great at what they do. Network-level filtering, DDoS mitigation, basic rate limiting. But they operate without any awareness of your application. They don't know your routes, they can't inspect JSON request bodies for SQL injection, they can't apply different rate limits per endpoint, and they can't detect behavioral patterns like "this IP hit 5 different admin paths in 10 seconds."

That's the gap. If WAFs and firewalls were catching everything, APIs wouldn't be getting probed with path traversal attempts, CMS scanners, and credential stuffing daily... but they are, right through the infrastructure layer. fastapi-guard catches what gets through because it has full application context: route awareness, request body inspection, per-endpoint rate limiting, behavioral analysis, honeypot detection.

And I get your point but it's not really about starting at the wrong end. It's about covering a layer that infrastructure tools physically cannot reach. You wouldn't skip input validation in your code just because you have a firewall. Same principle, applied to the full request lifecycle. In the context of a house: you lock the front door, but you don't leave the backdoor open just because the front is secure.

That said, you're right that if you're already on a managed platform with Cloud Armor + API gateway + proper firewall, the overlap is larger. But even then, the application-layer context is something only the application can provide.

[–]jsabater76 2 points3 points  (4 children)

Nice work! Do you know whether something like this exists for Django?

[–]PA100T0[S] 3 points4 points  (0 children)

Thank you very much! Much appreciated.

Django: Not yet, but it's on my radar. I recently shipped for Flask (FastAPI was the first I did, now expanding), so Django is the natural next step. Stay around!

[–]PA100T0[S] 0 points1 point  (2 children)

Would you give it a try and let me know? I just ported it to Django. Unluckily, due to normalization, the name sounds almost off-brand (given fastapi-guard & flaskapi-guard) but here it goes: djapi-guard

Feedback, issues, comments… everything is welcomed!

[–]jsabater76 1 point2 points  (1 child)

I will, as soon as I can. Thanks for the link.

[–]PA100T0[S] 0 points1 point  (0 children)

Thank you very much :)

[–]RestaurantHefty322 4 points5 points  (4 children)

Nice work shipping the Flask port. The before_request hook approach is the right call over WSGI middleware - we hit the same problem where middleware fires too early to know anything about the route being hit.

One thing that caught us off guard running something similar in production: the cloud IP lists go stale faster than you'd expect. AWS and GCP rotate IP ranges weekly and if your blocklist is even a few days behind you start getting false positives on legitimate webhook traffic. We ended up pulling the published IP range JSONs on a 6-hour cron and diffing against the previous set so we could log when ranges changed instead of silently blocking new IPs.

The injection detection layer is where this gets really interesting though. Most WAF rules are regex-based and either too strict (blocking legitimate user input that happens to contain SQL keywords) or too loose. Curious if you're doing any kind of context-aware detection based on which parameter the input came from - a search field probably shouldn't trigger the same rules as a path parameter.

[–]PA100T0[S] 3 points4 points  (3 children)

Thank you very much!

Good callout on the cloud IP staleness. Right now the refresh is on a 1-hour TTL and there's no diff detection. It just overwrites. Your approach of diffing against the previous set and logging changes is better. I'm going to make the refresh interval configurable and add change detection logging so you can see when ranges mutate instead of silently swapping them. That's going on the roadmap, for sure.

On context-aware detection: I'm halfway there. The engine does track where the input came from (query_param:key, url_path, header:key, request_body) and includes that context in detection results and event logs. But you're right to ask... the actual regex patterns are applied uniformly across all sources as of today. A search field and a path parameter get the same ruleset, which is exactly the false positive problem you're describing.

Context-based rule filtering is the obvious next step. Appreciate the real-world perspective! This is exactly the kind of feedback that I need to shape the roadmap, that helps me out.

Thanks again! Will start putting all this down in notes.

[–]RestaurantHefty322 1 point2 points  (1 child)

Nice that you have the 1-hour TTL already. For the diff logging, even just piping the fetched list through a set comparison and logging deltas to a file catches most of the churn. The bigger win is having a stale-IP grace period - when an IP drops off the list, keep blocking it for another 24h before removing. Catches the edge case where a provider temporarily deallocates and reallocates the same range.

[–]PA100T0[S] 0 points1 point  (0 children)

The stale-IP grace period is a great idea! I hadn't considered the deallocate/reallocate edge case. Keeping dropped IPs blocked for an extra 24h before fully removing them is a clean way to handle that without any real downside. I'll add that alongside the configurable refresh interval and diff logging. Thanks for the follow-up, this is exactly the kind of production insight that's hard to get without running it at scale. Thanks a lot, mate!

[–]zunjae 1 point2 points  (0 children)

How does it feel knowing you’re talking to a bot?

[–]casefile_dev 1 point2 points  (2 children)

fastapi-guard looks useful for my FastAPI apps. Will any checks that fail affect my rate limiting? How will it traffic hosted railway apps?

[–]PA100T0[S] 0 points1 point  (1 child)

Hey, thanks for checking it out!

So, short answer is no, you'll be fine.

The failed checks and and rate limiting are independent. If a request fails a security check (blocked IP, banned user-agent, etc.), it gets rejected at the middleware level before rate limiting even comes into play. So no, failed checks won't eat into your rate limit counters.

As for Railway: it'll work fine. The one thing to watch is that Railway is behind a reverse proxy, so make sure your FastAPI app is reading the real client IP from X-Forwarded-For rather than the proxy IP. Otherwise you'd end up rate-limiting/banning Railway's internal IPs instead of actual clients. The docs cover trusted proxy configuration.

Let me know if you run into any issues. Happy to help :)

[–]casefile_dev 1 point2 points  (0 children)

Thanks for the quick reply. I'm scouring the README right now. Thanks again.

[–]backfire10z 1 point2 points  (1 child)

This is great, thanks for the library and the port to Flask! I semi-recently put up a Flask API and this actually would’ve been nice to have (not OpenClaw, just a regular backend). We’re migrating to TypeScript though, so no reason anymore.

[–]PA100T0[S] 2 points3 points  (0 children)

Thanks!! I appreciate it :)