See the attack path first.
Relift audits the databases and hosts you own, verifies credentials you already hold, and joins what it finds into the attack thread that actually connects.
Version 0.2.0 · Linux and Windows · no drivers, no account
10.20.0.0/16 *.lab.pixelcity.dev db.internal deny 10.20.4.0/24 prod.internal One path down through four layers
The tool, at real size.
Fragments of the interface, not screenshots of a mock-up. The row below is output from a run against a lab MySQL server, carried through the three states that matter.
observed
One row from a real run. No CVSS guess, no adjectives — the credential was accepted and the server said so.
correlated
Rotate the credential, then find its source: config file, CI secret, backup, or an application default. Rotation without that step only resets the clock.
The thread names the stage that breaks it. Tick the box to rotate: the row resolves, and nothing else on the page needs to change.
broken
Relift attempts each credential once. A thread closes when the finding that carried it is gone, not when someone marks it resolved.


Every thread names where it breaks.
A finding is a fact. A thread is an argument about how the facts join up — and the one control that would have stopped it.
Stages
Every finding takes a stage. The thread will not draw a line between two stages that do not share an asset.
Confidence
High when the join is direct evidence, medium when it is an inference you should check yourself.
No invention
A thread is built only from findings in that run. An empty run produces no threads, not a generic one.
Rotate the credential, then find its source: config file, CI secret, backup, or an application default. Rotation without that step only resets the clock.
Break point
One control, written as an instruction: rotate the key, bind the listener, enable authentication.
Evidence
The bytes, headers or numbers that produced the stage sit next to it, not in a separate report.
Coverage
What ran and what did not is printed with the findings, so an empty section is a fact rather than an omission.
Three commands, one gate.
Write the scope, read the plan, then decide to send traffic. The plan is free; --execute is the only thing that touches the network.
The plan is the product
- target
- mysql://10.20.7.9:3306/app
- scope
- relift-lab · 10.20.0.0/16 · denies 10.20.4.0/24 · expires 2026-12-31
- profile
- lab — safe plus intrusive, because the scope allows it
- execute
- off. Six techniques are planned and none is sent until you say so.
# 1. write the allowlist relift init-scope --engagement lab \ --host 10.20.0.0/16 --deny 10.20.4.0/24 --out scope.json # 2. read the plan (no traffic) relift plan --target mysql://10.20.7.9:3306/app \ --scope scope.json # 3. send it relift scan --target mysql://10.20.7.9:3306/app \ --scope scope.json --execute # and the threads, from the stored run relift chains --run latest
Exit codes are part of the interface: 0 clean, 1 module errors, 2 refused by the gate, 3 bad usage. Nothing is scanned to find out which.
Measured, not promised.
The repository ships its own test suite and its own catalogue. Both numbers are read off the build in front of you.
The questions that decide it.
Do I need a scope file?
Yes. Nothing runs without one: an expiring allowlist with an owner, a risk ceiling and an audit log. Deny rules win, a wildcard never matches its apex, and a range wider than /22 is refused unless you say otherwise. That gate is the first thing the engine builds, not a wrapper around it.
Does it guess passwords?
No. There is no wordlist, no default-credential list and no retry loop anywhere in the tree. A database credential is verified once, against a host that already matches your scope, and the result is recorded as accepted, refused, or not attempted.
What does it leave on my servers?
Read-only protocol exchanges. It does not write rows, drop tables, dump schemas or upload files, and the intrusive techniques are the only ones that authenticate at all. The SQL injection check is capped at eight requests with a fixed payload set — no UNION, no stacked statements, no file reads.
Which databases does it speak?
PostgreSQL, MySQL and MariaDB, Redis, MongoDB, MSSQL, and Elasticsearch over HTTP. The wire codecs are hand-written: startup, SCRAM, TDS pre-login, RESP, BSON and OP_MSG. That is why there are no drivers to install and no version drift to chase.
Is the desktop app a different tool?
No. It serves the same runner over a loopback-only API with a per-launch token, and rejects any request carrying a foreign origin. The scope gate is the same code path as the CLI, so the window cannot talk its way past the tier ceiling.
Windows and Linux?
Both. The CLI ships as a single-file executable for each, and the desktop build is a single .exe or ELF binary with the UI bundled inside. The Python package and a portable zipapp are also on the release page.