fix: stop provisioning exposing wp-config.php - #303
Merged
Conversation
Phase 6 grants the service user write access to the site with a recursive chmod -R g+w so it can edit themes and plugins. That grant also sweeps in wp-config.php, which holds the database credentials, salts, and auth keys, leaving it world-readable and group-writable by a user that is a member of www-data. Two consequences, neither of which the agent needs: any local account can read the database credentials, and the coding agent can rewrite the file defining the site's database connection. The credentials file is now set to 0640 owned by www-data after the site-wide grant. PHP-FPM and nginx both run as www-data on a standard provision, so they keep working; world read and group write are gone. Applied unconditionally rather than only to fresh sites, so re-running provisioning corrects a mode an earlier install left loosened. Without that, every already-provisioned host stays exposed. Closes #302
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 6 of provisioning grants the service user write access to the site so it can edit themes and plugins:
The recursive grant also sweeps in
wp-config.php, which holds the database credentials, salts, and auth keys. Observed on two provisioned hosts:www-data— the coding agent can rewrite the file defining the site's database connection and security keys.The agent gains nothing from either. It needs to edit
wp-content;wp-config.phpis written once at install and read thereafter.Fix
harden_wp_config_permissionsruns after the site-wide grant and sets the credentials file to0640owned bywww-data. PHP-FPM and nginx both run aswww-dataon a standard provision, so they keep reading it; world read and group write are gone.Applied unconditionally, not only to fresh sites. This is the part that matters most: without it every already-provisioned host stays exposed, since nobody re-installs from scratch. Re-running provisioning now corrects a mode an earlier install left loosened.
A missing
wp-config.phpis not an error — provisioning may run before WordPress is installed.DRY_RUNstill routes throughrun_cmdso a dry run reports the calls it would make.Verified on two live sites
Applied
chmod 640by hand to both affected hosts before writing this, to confirm the fix is safe rather than assuming it:644 www-data:www-data640/register/,/shop/all 200; registration block still renders664 <service-user>:www-data640/wp-login.php200; WP-CLI reads optionsNothing broke on either.
Tests
tests/wp-config-permissions.sh, following the convention intests/cli-channel-perms.sh— the function is extracted and exercised against a temp site withchownrecorded rather than performed, since the suite does not run as root.Covers:
664) is tightened to640wp-config.phpdoes not fail the phaseVerified load-bearing: reverting the mode to
664fails the new test withexpected 0640 after hardening, got 0664.Full suite: 33 passed, 3 failed —
cli-channel-binary-path,datamachine-worker, andkimaki-agent-fallbackall fail identically on pristinemainwith these changes stashed, so they are pre-existing and unrelated.Deliberately not included
Whether the grant should scope to
wp-contentrather than$SITE_PATHis a larger question. Core files are replaced wholesale by WordPress updates and are not something an agent should be editing in place, so a narrower grant would express the intended capability more precisely. That is a behavior change worth discussing separately rather than folding into a security fix.Closes #302