Repository navigation
fix: harden the wordpress nginx configuration - #26
Merged
Merged
Conversation
Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
vitormattos
approved these changes
Nov 14, 2026
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.
What was wrong
The WordPress nginx configuration served every file in the document root and executed every
.phpfile it found:.phpfile executed, including files underwp-content/uploads,wp-content/cache, the document root andwp-includes. Onlyvendorfolders were excluded, so a single file write became remote code execution..ht*and.git*),composer.lock,package.json,phpunit.xml.distand thetestsfolders of the cloned plugins were served as static files. Folders that plugins protect only with.htaccess(backups,wc-logs,woocommerce_uploads) were readable because nginx ignores.htaccess.xmlrpc.phpanswered requests, althoughWORDPRESS_XMLRPC_ENABLED: 0suggested otherwise.client_max_body_size 0removed the request size limit, so any request body was buffered to disk whatever its size.What changed
index,wp-login,wp-cron,wp-comments-post,wp-signup,wp-activate,wp-trackbackandwp-links-opmlin the root,wp-admin/*.php,wp-admin/network/*.php,wp-admin/user/*.phpandwp-includes/js/tinymce/wp-tinymce.php. Any other.php,.php[0-9],.phtml,.pharor.phtpath, in any letter case, returns 404. This covers the wholewp-content..sql,.sqlite,.bak,.old,.orig,.save,.swp,.swo,.log,.sh,.dist,.lock,.tar,.tgz,.gz,.bz2,.xz,.7z,.rar,.wpress,.env,.ini,.neon,.yml,.yaml,.mdor~;composer.json,composer.lock,package.json,package-lock.jsonandphpunit*.xml(.dist);.zipfiles, except in thewp-content/uploads/YYYY/MM/media folders;wp-content/debug.log,updraft,ai1wm-backups,aiowps_backups,backup*,upgrade,upgrade-temp-backup,cacheandlogs;wp-content/uploads/wc-logs,woocommerce_uploadsanddebug-log-manager;tests,stubs,node_modulesandvendor-binat the root of a plugin or theme, and anyvendororvendor-binfolder underwp-content, except stylesheets, scripts, images and fonts invendor, which the theme (assets/vendor), WooCommerce and Kadence Blocks enqueue;.well-known.location = /xmlrpc.phpis denied.client_max_body_sizeis10m, the same aspost_max_size.The same rules are proposed for the image in LibreCodeCoop/wordpress-docker#42 and LibreCodeCoop/wordpress-docker#43. Once they are merged and the submodule is bumped, this file can be dropped in favour of the image configuration plus the SaaS-specific settings in
server.d.How it was verified
saas-e2estack built from scratch with this configuration: 14 passed. The nginx log of the run has no 403, 404, 413 or 5xx response.mainconfiguration and through this one, and removed afterwards:main.phpinuploads(bodyEXECUTOUonmain).PHPand.phtmlinuploads,.phpin the root.phpinwp-content/cachewp-includes/version.php,wp-admin/includes/file.php.sql,.tar.gzand.zipinuploads,wp-content/debug.log, a backup folder,wp-config.php~,/.env.zipinuploads/2026/11/composer.lock,package.json,phpunit.xml.dist,tests/*.phpvendor/composer/installed.jsonPOST /xmlrpc.phpPOST /wp-login.phpwp-login.php,wp-cron.php,wp-admin/admin-ajax.php,/wp-json/vendor,wp-includes/js,/.well-known/