BASIS SDK
BASIS (Behavioral Anomaly Security & Intelligence System) is a pip-installable Django app that learns what an application's ordinary traffic looks like and flags actors who stop matching it. It ships as middleware plus a staff-only dashboard, and it comes with the attack scenarios and benchmark harness used to measure whether the detection actually holds. Built as my Bachelor's engineering thesis.
Pipeline
- Attack simulation
- Live application
- Request telemetry
- Feature windows
- ML detection
- Risk score
- Dashboard
Problem
Signature rules and WAF policies describe attacks somebody has already seen. They are good at the known cases and structurally blind to everything else — which is most of what an application will actually get hit by.
But an application's own traffic has a shape. Its endpoints get visited in recognisable orders, at recognisable rates, with recognisable database and response costs. The question BASIS is built around is whether that shape can be learned from ordinary middleware-level telemetry, with no labelled attack data, and whether departures from it are specific enough to be worth alerting on.
Approach
BASIS scores one actor over one time window, not one request. A single request carries almost no behavioural information; five minutes of an actor's requests carries volume, pacing, endpoint traversal, authentication outcomes and query cost — enough to be judged.
Isolation Forest is the primary detector, with One-Class SVM, Local Outlier Factor and a statistical baseline kept alongside it as comparisons rather than decoration: the benchmark suite scores all four on the same synthetic scenarios. Scores are emitted as percentile ranks against the training distribution, which makes the alert threshold directly interpretable — a threshold of 0.95 is a stated 5% expected false-positive rate, not an arbitrary dial.
Architecture
- collectors/ — pulls raw signals off each request: HTTP metadata, authentication behaviour, database interaction patterns.
- detection/ — turns telemetry into feature vectors, maintains per-application baselines, scores windows with explainable output, and adapts the baseline over time.
- detection/models/ — the four detector implementations behind a common interface.
- dashboard/ — a staff-only Django dashboard: live request stream, anomaly investigation views, baseline state, feature drift, endpoint-transition map, model benchmarks and health checks.
- experiments/ — traffic generators and attack scenarios that drive a real server over real HTTP, plus a deterministic benchmark harness.
Implementation notes
Baseline adaptation is trust-weighted. Windows that score above the trust threshold are withheld from future retraining, so an attacker who runs slowly cannot walk the baseline toward their own behaviour — the poisoning defence was hardened against a measured attack rather than assumed.
The demo is a real Django storefront with BASIS wired in as an observer, and the experiment scripts drive it over genuine HTTP: normal shoppers, brute-force login, credential stuffing, scraper enumeration, checkout fraud bursts, injection probes and a DDoS burst. Nothing writes to the database directly, so what the dashboard shows is what a real visitor or attacker would have produced.
Live scoring is a separate concern from measurement. The traffic scripts depend on wall-clock timing and on whatever else is in the database, which makes them the right tool for verifying the pipeline and the wrong one for judging detector quality. A separate benchmark harness synthesises labelled telemetry with a fixed seed, pushes it through the real feature pipeline and the real detector classes, and reports per-model, per-scenario numbers that reproduce exactly.
Observations
Measured through the benchmark suite, Isolation Forest's mean recall across seven attack scenarios climbs with baseline size — roughly 0.14 at 25 training windows, 0.48 at 50, 0.86 at 100, and 1.00 at 300. That curve is the reason the default minimum training size is set where it is.
Distributed credential stuffing is recorded as NOT SCORED rather than as a failure. It opens a fresh session per attempt, so per-actor aggregation never accumulates enough of any one actor to judge. That is an architectural blind spot in the design, and the benchmark reports it as one instead of hiding it inside an average.
What I learned
The failure mode that worried me most turned out to be the quiet one. An under-trained baseline does not throw errors — it reports an anomaly rate of zero, which is indistinguishable from a healthy application. Most of the cold-start handling exists because of that: a system that cannot yet judge has to say so out loud.
Feature engineering mattered more than model choice. Letting sparse endpoint-transition columns outnumber the dense behavioural features quietly stopped Isolation Forest responding to anomalies at all, because it splits on one randomly chosen feature at a time. Capping them fixed a problem no amount of retuning the model would have.