That is a claim about a dependency graph, which makes it a claim anybody can check. So the first section is how, and it takes about thirty seconds.
Check it yourself
Copy this. It clones the repository and greps the whole dependency graph:
$ git clone https://github.com/DBSloop/sloop && cd sloop/cli$ cargo tree --edges normal,build,dev --target all --all-features \$ --prefix none | awk 'NF{print $1}' | sort -u \$ | grep -Ei 'reqwest|hyper|ureq|isahc|curl|ssh2|russh|thrussh'# nothing. That is the whole result.It prints nothing, and nothing is the result. 269 crates go into that binary and not one of them can open a socket — --edges normal,build,dev so a build-dependency cannot hide there, and --target all because something behind [target.'cfg(windows)'.dependencies] is invisible to a plain cargo tree run on Linux, which is precisely where it would hide.
The same check is a script in the repository, and it runs on every push. It fails the build rather than printing a warning:
$ sh ci/no-http-client.shno-http-client: 269 crates in the graph, not one of them opens a socket.SSH clients are denied too, and that is not an afterthought: ssh2, libssh2-sys, russh, thrussh, async-ssh2-*, ssh-rs and makiko fail the build beside reqwest and hyper. An embedded SSH client can open a socket to anywhere, so the promise above would stop being true while a check that only looked for HTTP clients still passed. A claim that holds only because the check is narrow is not worth making — which is why sloop runs your own ssh instead.
A registry holds a route, never a value
There is no spelling of a password a registry will accept. It stores which of four routes to take, and the value is fetched at the moment it is needed — which is what makes it impossible to put a password there by accident.
sloop db list shows the route beside every database and cannot show a password, because there is not one there to show. Databases and registries has that listing.
Nothing in argv, so nothing in ps
A password reaches a child process through a pipe, or through that one child's environment — never as a command-line argument. Anybody running ps on a shared machine while a backup is going sees the command and not the credential.
Which leaves one hole sloop cannot close: a password you typed into a URL was already in your shell's history and in ps before sloop ever ran. It says so rather than quietly accepting it, and then keeps its own half of the bargain:
$ sloop db add leaky --url 'postgres://app:hunter2@db.internal:5432/orders' \$ --log-file run.log▲ The password came from the URL it was visible in `ps` and is in your shell history while thatcommand line lives. sloop has filed it and will not write it anywhere —--password-stdin avoids the exposure next timeregistered leaky in the project registry, password from the OS keyring postgres://app@db.internal:5432/orders $ cat run.log▲ The password came from the URL it was visible in `ps` and is in your shell history while thatcommand line lives. sloop has filed it and will not write it anywhere —--password-stdin avoids the exposure next timeregistered leaky in the project registry, password from the OS keyring postgres://app@db.internal:5432/orders ← no password, anywhereA log you could paste into a public issue
--log-file writes what the run printed, without colour and with anything that reads like a credential removed. That holds for two reasons, and only one of them is a filter.
The structural half: the one line that carries a real password goes through a function that has no logging in it at all. sloop does not redact its own passwords out of its logs — it never writes them.
The net under it is for credentials that arrive inside something else: a URL with a password in it, a key=value pair whose key says what it is, or a word after something that announces a secret. Like a token inside a --password-command you wrote, which sloop cannot see coming:
# the terminal shows the command the user typed$ sloop db add vaulted --url … --log-file run2.log \$ --password-from "curl -H 'Authorization: Bearer sk-live-abc123' https://vault/pw"note: … password from the command `curl -H 'Authorization: Bearer sk-live-abc123' https://vault/pw` # the log does not$ cat run2.lognote: … password from the command `curl -H 'Authorization: Bearer *** https://vault/pw`Config is parsed, never evaluated
Real passwords contain $, backticks, >, #, quotes, pipes, backslashes and spaces. Nothing sloop reads is ever sourced or eval'd, so none of that is interpreted. Here is a PostgreSQL role whose password is nothing but metacharacters:
# the role's real password on the server:# p@ss$HOME `whoami` >out #1 "q" |pipe \slash$ sloop db add awkward --url postgres://app@127.0.0.1:5449/orders \$ --password-stdin --test # piped in, never an argument✓ postgres 17.9 not encryptedregistered awkward in the project registry, password from the OS keyring # and a later run, reading it back out of the keyring:$ sloop db test awkwardawkward postgres://app@127.0.0.1:5449/orders project✓ postgres 17.9 not encrypted ← it connected Registered through a pipe, stored in the keyring, and read back on a later run to open a real connection. $HOME did not expand, the backticks did not execute, the > did not redirect and the # did not start a comment.
A \r is the one character sloop removes — Windows editors add them, and the authentication failure that follows is invisible.
What this is not
None of it is a substitute for the database's own access control. sloop runs as you, with the credentials you gave it, and can do exactly what those credentials allow — the privileges a backup role needs is the page for keeping that set small. And an encrypted backup is only as safe as the key: lose it and the backups are unreadable, leave it beside them and they are not protected.
Securing the machine and the network is still the operator's job. What sloop guarantees is narrower and checkable: it cannot send your credentials anywhere, because it cannot send anything anywhere.