Correlation: many signals, one risk
Every tool you own answers one question. The failure that hurts you is the one that needs four of those answers at once, and no single console has three of them.
The problem
A workflow file changes in a repository that holds deploy credentials. A certificate is issued by a hierarchy whose keys later turn out to be recoverable. A key that has never been used against this account validates for the first time, and forty minutes later something enumerates the model APIs it can reach.
Four findings, four tools, four severity labels that mean different things. None of them is worth waking anyone for. Together they describe a breach that is already in progress.
This is not a volume problem. Teams that halve alert volume still miss these, because the information needed to judge them lives in products that do not know about each other's existence.
How Hanu approaches it
Collectors normalise everything into one typed shape before anything reasons about it. There are 166 signal types covering cloud posture, identity, code, CI/CD, certificates, containers, Kubernetes, data, AI workloads and runtime. An engine's only job is to emit the right type with the right fields populated — it does not decide whether the finding matters.
Correlation then runs in two tiers over that stream. Tier 1 asks whether one observation is unusual *for you*: has this principal ever been seen, was this resource public yesterday, has this key ever been validated. Tier 2 asks whether observations from different places, inside a bounded window, describe one sequence. Only tier 2 produces a compound risk.
Both tiers are declarative rules registered in an index array, each with its ATT&CK technique, its evidence fields and a test. The 609 behavioural detections map to 96 ATT&CK techniques. A registration guard fails the build if a rule is exported but never wired into the tier index — the failure mode that makes detection catalogues quietly wrong over time.
Scoring you can recompute
A compound risk carries a score assembled by arithmetic. There is no model anywhere in the path, which matters less for purity than for the practical reason that a score nobody can recompute is a score nobody can defend.
| Input | Effect |
|---|---|
| Severity base from the rule | 9 for CRITICAL, 7 for HIGH |
| Each additional contributing signal | +0.5, capped at +2 |
| Reaches a publicly exposed asset | × 1.3 |
| Reaches a crown-jewel asset | × 1.6 |
| Appears in known-exploited intelligence | × 1.5 |
| Ceiling | 10.0 |
Read as arithmetic rather than as an incident, a chain that reaches a crown-jewel asset from a public entry point saturates the ceiling quickly. That is the intended behaviour: the top of the queue is reserved for chains where the reach is already established, and everything below it is ordered by how close it got.
What you get
COR-01One queue instead of five
COR-02The score's working, attached
COR-03Rules small enough to read
COR-04Response where the work already is
Limits
Correlation cannot join what was never collected. A resource type with no collector is invisible to the graph — Oracle Cloud exists in the codebase as stubs only and is not supported, and any provider you have not connected does not exist as far as a chain is concerned.
Joins depend on stable identifiers. Where a provider exposes a real fingerprint the match is exact; where it exposes only a name, the signal records identifierQuality: "name-pattern" so a reviewer knows the join is a heuristic rather than a fact.
Windows are declared per rule and are not learned. That is deliberate — a threshold that changes on its own is a threshold nobody can regression-test — but it does mean an unusually patient attack that spaces its stages over days will not fuse into one risk. It will still appear as separate findings, which is worse than a compound risk and better than nothing.
There is no tactic-level ATT&CK mapping file in the repository, so we do not publish a "tactics covered" figure. Technique mappings exist per rule; a tactic rollup is not something we can currently reproduce with a command.
Questions
Does anything use a model to decide what is risky?
What happens when two rules fire on the same signals?
Can we add our own signals and correlation rules?
How does this relate to the SIEM we already run?
Run it in your own account
One Docker Compose stack, your datastores, read-only credentials into your clouds. The Community edition is free to run in production.