Files
webhooker/internal/database/sqlite_mode_test.go
sneak 1230ae990e
All checks were successful
check / check (push) Successful in 3m24s
Create every SQLite file 0600 (closes #255)
webhooker.db holds target configuration in plaintext — bearer tokens,
API keys, Slack webhook URLs — and the session encryption key, and it
was created 0644. The 0750 data directory was therefore the only
barrier, and a Docker bind mount supplies that directory at 0755,
which removes it: every local user on the host could read every stored
credential.

The mode is settled in OpenSQLite, the single open path all three
tiers share, so the main database, the per-webhook event databases and
the archive databases are covered in one place.

0644 comes from SQLite itself: robust_open substitutes
SQLITE_DEFAULT_FILE_PERMISSIONS whenever it is handed mode 0, and
findCreateFileMode yields 0 for a main database opened by URI with no
`modeof` parameter. A chmod after opening would leave a window in
which the credentials are on disk world-readable, so OpenSQLite
creates the file itself at 0600 before the driver sees the path.

That also settles the WAL sidecars, which carry the same rows and
would otherwise leave the fix worthless. SQLite derives both from the
main database file — `-wal` through findCreateFileMode, which stats
the path with the suffix stripped, and `-shm` in unixOpenSharedMemory
from an fstat of the open database descriptor — so a main file at 0600
produces sidecars at 0600. Verified by stat rather than by reading the
driver: a pre-change build leaves webhooker.db, -wal and -shm all 644;
this one leaves all three 600, in a 0755 bind mount, for all three
tiers, with delivery and restart working.

Existing files are chmodded on open, so a directory an earlier build
left 0644 — including a developer's scratch directory — is fixed
without any migration machinery.

This is not encryption at rest. An unattended process needs a key it
can read without a human, so the key lands beside the data and an
attacker who can read the database can read it too.

The data directory stays 0750: the group bit may matter to a
deployment, and with the files at 0600 the directory is no longer the
barrier.

README: the Docker section now states the DATA_DIR ownership
requirement where the bind mount is documented. A `-v` source path
Docker creates is root:root, and the container runs as UID 1000, so it
fails to start on the lock file; the chown that fixes it appeared only
under Restore.
2026-08-24 02:10:14 +00:00

6.9 KiB