Skip to content
zit Artifact [10803cbf5c]
Login

Artifact [10803cbf5c]

Artifact 10803cbf5c570ac04560e10d25592d9007d816d1733df4197e5fb4080ba04457:

Instance of technote [c2e5f91720] - A password is not a thing to send in the clear by dmestas on 2026-09-24 17:16:56.
C A\spassword\sis\snot\sa\sthing\sto\ssend\sin\sthe\sclear
D 2026-09-26T17:56:41.461
E 2026-09-24T17:16:56 c2e5f91720d9414e883e8b0025626fb3605ed023
N text/x-markdown
U dmestas
W 2100
# A password is not a thing to send in the clear

0.3.30 stops zit sending a password over plain `http://` to another host,
and stops a redirect from carrying one to a different host.

When a server gates reads behind HTTP Basic, zit answers the challenge with
the password it was given. It did that whatever the URL's scheme. Basic is
the password base64-encoded, which is an encoding, not protection; over
`http://` it crossed the network readable by anyone on the path, and because
a clone saves its URL as the checkout's remote, every later pull and push
sent it again. Against a test server on a LAN address, 0.3.29 sent
`Authorization: Basic YWxpY2U6czNjcmV0` — `alice:s3cret` — in the clear.
0.3.30, given the same command, sent nothing and said:

```
zit clone: refusing to send credentials over unencrypted http://…; use https://…
```

Where the check sits matters. It runs when the challenge arrives, not when a
password is supplied, because at that point nobody knows whether one will be
needed. A public repository cloned over http with `--user` is never
challenged, and still works. Loopback is exempt — `localhost`, `127.0.0.0/8`,
`::1` — because plaintext there never leaves the machine, and that is how a
forge talks to its own zit and how the tests run. A name that only looks like
loopback, such as `127.evil.example`, is not.

The report asked about http. Tracing it turned up the same leak by a second
route. Once a challenge was answered, the password rode on every later
request in the exchange, and a followed redirect rewrote the target to
wherever `Location` pointed. Any server could forward the password to a host
of its choosing by answering `302`. A redirect that changes host now drops
the credential for the rest of the exchange, which is what curl and browsers
have long done. A redirect from https down to http was already refused,
credential or not.

Plain http to another host now also prints one line on stderr, from every
verb that syncs. It is not only about passwords: a private repository's
content crosses readable too, whatever authenticates it.

Z 85449478c3d6d70c16e8b913358cdd6f