Stop bulk lockouts before
they reach your directory.
SCORPION protect sits between your clients and your real directory server (AD, OpenLDAP, 389 DS). Every ordinary request passes through byte-for-byte, untouched — but a runaway script or an over-eager AI agent trying to lock, delete, or reset thousands of accounts hits a configurable blast-radius policy first, and never reaches the directory at all.
The problem
Directory protocols trust the caller completely.
LDAP has no concept of "that's a lot of accounts at once." A misconfigured script, a compromised credential, or an AI agent given just enough access to "clean up stale accounts" can lock, delete, or reset a huge slice of your directory in the time it takes a human to notice — and by the time they do, it's already done.
is the difference between a scoped cleanup script and one that iterates every entry in the directory instead of the ten it meant to.
is enough for an automated caller with valid credentials to lock or delete accounts faster than any human review process can react.
are needed anywhere else — ai-protect drops in as a TCP hop between client and directory, no directory-side config required.
How it works
Decode only what matters. Forward everything else.
ai-protect parses just enough of the wire protocol to recognize account-lock modifications, deletes, creates, renames/moves, and password-reset extended operations. Every other request is relayed byte-for-byte — it never has to understand your whole schema to protect it.
What's built in
Everything a proxy sitting in front of production auth needs.
Transparent by default
Only frames the system needs to act on are parsed. Everything else forwards byte-for-byte, both directions, concurrently.
Configurable blast-radius policy
Block any single request over a per-request cap, plus a sliding-window cap per identity or globally as a backstop.
Verified identity, not IP guesswork
Keys policy off a simple bind DN only once its BindResponse confirms success — closing identity-churn bypass gaps.
TLS on every hop, independently
LDAPS or plaintext-then-StartTLS on client and upstream sides, each optional and each with its own mutual-TLS support.
Load balancing & failover
Round-robin, random, or least-connections across upstream targets, with automatic failover and passive health tracking.
Structured audit logging
Every allow and block decision, stdout + newline-JSON to disk — the forensic trail, decoupled from policy logic.
Zero-downtime policy reload
SIGHUP hot-reloads policy files; SIGTERM/SIGINT drains in-flight connections before shutdown.
Metrics, health checks, fuzzing
Prometheus metrics, liveness/readiness endpoints, and a cargo-fuzz harness on every byte parsed off the wire.
Policy as config
One TOML file. No redeploy to tune.
Policy lives in its own gitignored file, separate from network config, so it can change on its own cadence — and reload on SIGHUP without dropping a connection.
- ✓ Per-request cap blocks a single oversized operation outright.
- ✓ Sliding-window cap catches an identity accumulating damage over time.
- ✓ PerIdentity or Global scope — stack both as a layered backstop.
- ✓ Optional SQLite or Redis/Valkey backing so history survives a restart or spans instances.
[[policy]] type = "threshold" scope = "per_identity" max_per_request = 10 max_per_window = 50 window_secs = 60 # shared backstop no single identity can reset [[policy]] type = "threshold" scope = "global" max_per_request = 25 max_per_window = 200 window_secs = 60 state_db = "policy-state.sqlite"
Read more
Design docs, not just a README.
End-user docs: install, configure, and how the LDAP policy behaves in practice.
Full request lifecycle, component design, and extension points.
Module map and conventions for anyone — human or agent — working on the code.
The honest gap list between today and a production-ready deployment.
Get started
Up and running in about a minute.
Point ai-protect at your real directory, copy the example config and policy files, and run it. Every client just needs to talk to a new port instead.
git clonethe repo &cargo buildcp config.example.toml config.tomlcp policies/ldap.example.toml policies/ldap.tomlcargo run— listens on127.0.0.1:3890- Point clients at ai-protect instead of the directory