Skip to content

Security: Lock down first-run installer and remove force-reinstall bypass #1

Description

@fvent01

Finding

public/install.php exposes a browser-based installer that writes application configuration, creates the database/schema, and seeds the first administrator. Installation state can be bypassed with ?force=1, and the visible POST flow does not use CSRF protection or a one-time setup capability.

Risk

Anyone who can reach an incompletely configured or force-enabled installer may be able to alter database settings, overwrite configuration, create or replace administrator access, disclose connection errors, and trigger schema changes. Cross-site requests can also target the installer because no synchronizer token is required.

Evidence

  • Installed state is bypassed with isset($_GET['force']).
  • The wizard stores database credentials in the installer session and writes config/config.php.
  • Step 2 and Step 3 POST handlers do not validate a CSRF token.
  • Database exception text is displayed to the browser.

Recommended remediation

  • Make the installer first-run-only with a server-side lock that cannot be bypassed by a query parameter.
  • Require local CLI setup or a random, expiring, single-use setup token generated out of band.
  • Deny non-loopback access by default.
  • Add CSRF protection to every installer POST.
  • Never expose raw database exceptions or filesystem paths to the browser.
  • Rotate the installer session ID between privilege-sensitive steps and use Secure/HttpOnly/SameSite cookies.
  • Refuse to overwrite an existing configuration unless a separately authenticated recovery workflow is used.

Acceptance criteria

  • ?force=1 cannot reactivate installation.
  • Remote first-run setup requires an explicit one-time capability.
  • Cross-site POSTs cannot advance or execute the installer.
  • Existing configuration and admin accounts cannot be replaced anonymously.
  • Internal database errors are logged, not displayed.
  • Tests cover fresh install, completed install, forced access, CSRF, expired setup token, and replay.

Priority

P0 — unauthenticated administrative setup surface.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions