Version: 4.1
3.9.2
This is a security release. Update.
Security
- A site scan could read files outside the site. Three WordPress
vulnerability-scan routes took a
domain/subfolderparameter, checked that the account owned the domain half, and then used the whole parameter as a path. A percent-encoded..survives Go's path cleaning, so a request could walk out of the document root — and the same handler read the result back to the caller, so it was readable, not just reachable (#731, and its CLI half). - Four places acted on what a request named rather than what had been checked: FTP account changes, deleting a mailbox, adding a DNS record, and creating a domain through the REST API (#731).
- A name could be registered under another account's DNS zone, and its records were written into that account's zone file. The old check asked who owned the registrable root the public suffix list derives, while the write goes to the nearest ancestor that actually has a zone file — often lower down (#727).
- Root wrote to predictable
/tmppaths in eleven places. The worst were a shell script root then executed, a repository package root then installed, and the panel's own binaries downloaded to a guessable name and installed into/usr/local/bin(#727). - A support report contained the MySQL password (#727).
- The CLI exited 0 when a command failed, so an API caller creating an account or changing a password was told it had worked when it had not (#727).
Fixed
- Every page that saves through the browser's own form now saves. The
panel's pages submit with
FormData, which is a multipart body, and neither engine read one — so the field a customer typed arrived empty, the handler refused the form, and the page reported success anyway. It affected 47 pages, including Add Domain, every application installer, the file manager, backups, PHP and Site Manager (#726). /emails/newanswered "the panel engine is not running" while it was running. A plan'semail_limitis an integer and was read as a string; the database driver refused the conversion and the request was never answered. The message now says what it knows and points at the log (#729).- amavisd could not start on any server we have built. It binds
::1and needs two Perl modules to do so; they were never installed, so it died at start-up and systemd reported only a timeout. Mail content filtering has not been running (#727). - A feature set added by a release never reached an existing server. Feature sets were only ever copied on a fresh install, so a plan could not be sold on one introduced later (#727).
Added
- A mail plan sells mail, and its quota is its storage. Leave the disk figure empty and enter a mailbox quota, and that quota is the plan's disk: a mail-only product. Enter both and the mailbox is a carve-out that may not exceed the plan (#722).
- The Document Root form is honest about where a site can live. The site directory is fixed to the account's own path — it used to be a free text field, so any path on the machine could be typed and the refusal only arrived after Save — and the running directory takes a custom path beside the four framework presets (#730).
- 34 rarely-used pages moved off the sidebar onto the dashboard. Every one of them is still reachable, and a test now fails if a menu link is drawn in neither place (#724).
- The public website can be put behind a password without breaking deploys (#728).
The update checks itself
version/3.9.2/UPDATE.sh asks whether this server carries each fix rather
than assuming the files landed: it replays one form into the engine twice,
urlencoded and multipart, and requires the two answers to agree; it checks
amavis's Perl modules and whether amavisd is actually running; and it names
the two CLI files that must carry their fixes. It exits non-zero if a check
fails, and the update reports that as a failure rather than printing success
over the top of it.
Documentation
- 3.9.1 (#725).
Was this helpful?