A proper login page with a username, the Web UI password stored as a hash instead of plaintext, and a warning when a remote host is reachable in the clear. Nothing to do on upgrade.
A login page, a username, and the password off the disk
The Web UI used HTTP Basic Auth, so what you got was the browser's own password box — not a page of the application, and nothing a password manager could fill in. There was no username either: the header was split into user and password and the user half was then never looked at. And the password sat in plaintext in settings.json as well as in your compose file (#60, @NotRetarded, who asked for all three).
Now there is a real form at /login, marked up so a password manager recognises it, and WEB_USERNAME — optional, empty by default, so an upgrade cannot lock anyone out. The stored password is a scrypt hash; an existing plaintext one is migrated to a hash the first time the new version starts.
Nothing you rely on breaks. WEB_PASSWORD is an environment variable and so plaintext by nature, and a plaintext stored value still verifies. curl -u still works: a browser gets redirected to the form, a script still gets its 401. Sessions have an idle timeout (WEB_SESSION_HOURS, default 8) and an absolute one (WEB_SESSION_MAX_DAYS, default 7); they live in memory, so a restart signs everyone out, and changing the password ends every session.
No HTTPS, and that is a decision rather than something half-finished. Put a reverse proxy in front of this if you expose it beyond your own network — it does certificates, including renewal, better than we would.
A tcp:// remote host is in the clear, and now says so
A reverse proxy protects the Web UI, which people come in to. It does nothing for the connection that goes out from Docksentry to a remote Docker daemon — that link never passes through it (#60). On a plain tcp:// endpoint that link has no encryption and no authentication at all: reaching the port is enough to start a container that mounts the host filesystem.
docs/security.md now has a multi-host section comparing the transports, the README example uses ssh:// for both hosts instead of leaving a tcp:// one next to it unremarked, and Docksentry warns at startup, naming any tcp:// host that leaves the machine.
The weekly report reaches every channel that is on
It went to Telegram and the two webhooks and nothing else — never e-mail, ntfy, Gotify, Matrix or Apprise, and it decided by whether a webhook URL was set rather than whether the channel was on, so a switched-off Discord webhook still got it and you got the report twice (#59, @NotRetarded). Recipients come from the notifier layer now, so a channel that is on gets it once and a channel that is off gets nothing. It could also mark itself sent without sending — Telegram bot present but its channel off, no other channel — and skip the week silently; that is closed too.
The Connections page shows your API tokens
API_TOKENS was the one setting the interface said nothing about — not the values, which is right, but not even whether any existed. It shows the token names now and when each was last used, never the tokens themselves, and it tells you when a saved value is overruling the environment variable or when an entry has no secret after the colon and so can never match.
And
- The audit trail is findable by searching for "audit" — its heading is translated in all 16 languages and none of them contained the word.
docs/configuration.mdis grouped and sorted — twelve sections by purpose, alphabetical within each, instead of 81 rows in no order.- "Guild" and "Server" no longer disagree. Discord's interface says Server, its API says Guild; the variable keeps its name but
DISCORD_SERVER_IDis accepted too, and the log lines say "server". - Discord slash commands suggest host and container names as you type, so you no longer have to know that the local host is called
local. - The new login code went through an adversarial security review before this release; the findings, including an open-redirect / header-injection in the post-login
next=parameter, are in the changelog.