Skip to content

Add randomized SQLite database storage - #494

Open
JanJakes wants to merge 2 commits into
trunkfrom
database-access
Open

Add randomized SQLite database storage#494
JanJakes wants to merge 2 commits into
trunkfrom
database-access

Conversation

@JanJakes

Copy link
Copy Markdown
Member

Summary

This PR adds randomized storage for SQLite databases as an additional layer of protection against direct web access.

  • Randomized paths: New managed databases are stored in a directory generated from 128 bits of randomness.
  • Portable discovery: db-path.php records the database location relative to the managed database root.
  • Automatic migration: Existing .ht.sqlite and .ht.sqlite.php databases are moved to the randomized layout.
  • Explicit path compatibility: User-configured database paths and :memory: continue to work unchanged.
  • Safer failures: Filesystem errors do not expose the randomized database path.

Managed storage

When no explicit database path is configured, the default layout is:

wp-content/
└── database/
    ├── .htaccess
    ├── index.php
    ├── .ht.sqlite.lock
    ├── db-path.php
    └── .ht.<32-hex-char-random-key>/
        ├── .htaccess
        ├── index.php
        └── .ht.sqlite

The db-path.php file returns the database location using __DIR__, so copying or moving the complete database directory keeps the reference valid. The storage manager also restores missing directories, protection files, and the database file when needed.

Legacy migration

Migration is serialized across concurrent requests. Before moving a legacy database, the storage manager checkpoints WAL data, switches to DELETE journal mode, and acquires an exclusive SQLite lock. If the database remains busy or migration otherwise fails, the original database file stays in place.

Why

A SQLite database at a predictable location under the document root may be served directly when the web server does not honor .htaccess or equivalent denial rules. The randomized directory makes accidental exposure substantially harder while retaining a stable discovery mechanism for WordPress and external tools.

This is an additional safeguard, not a replacement for private storage. Keeping the database outside the document root or configuring the web server to deny access remains the strongest protection.

Store new databases in a protected randomized directory and record the relative location in a portable manifest. Preserve existing fixed database paths for a separate migration step.
Move fixed database files into randomized storage automatically before opening SQLite. Serialize concurrent requests, checkpoint WAL, refuse busy or ambiguous storage, and preserve legacy files when migration fails.
@JanJakes
JanJakes marked this pull request as ready for review August 21, 2026 14:21
@JanJakes
JanJakes requested a review from adamziel August 21, 2026 14:21
@adamziel

Copy link
Copy Markdown
Collaborator

The idea looks great. I don't have a good understanding why is the .ht.sqlite.lock file outside of the .ht.<hash> directory, but that also doesn't matter too much. I won't be able to review this deeply before my afk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants