Join our Newsletter — 33% off our NHI Course
Home› Guides› PHP and WordPress Security Guide: Core, Plugins, Secrets…
Guide Application Security

PHP and WordPress Security Guide: Core, Plugins, Secrets and Hardening

PDF for newsletter subscribers · free to read online

← All guides
By Lalit Choda, NHI Mgmt Group Updated 24 October 2026 18 min read
On this page

Most PHP and WordPress compromises do not start with an exotic exploit: they start with an outdated PHP branch, an unpatched plugin, or an API key sitting in a database row that any unauthenticated request can read. WordPress core is well maintained and patches itself by default, but the ecosystem around it (plugins, themes, hosting control panels and the PHP runtime) carries most of the risk. This guide covers supported PHP versions, php.ini and PHP-FPM settings, WordPress core hardening, plugin risk, application passwords and REST API exposure, wp-config secrets, automatic updates and Composer dependency auditing. It is written for administrators, developers and security teams who run WordPress sites or custom PHP applications, and it assumes you can change server configuration, not only the WordPress dashboard.

Key takeaways

  • Run a supported PHP branch. As of October 2026 the php.net supported branches are 8.2 (security fixes only, ending 31 December 2026), 8.3, 8.4 and 8.5; PHP 8.1 reached end of life on 31 December 2025.
  • Plugins are the attack surface. Patchstack counted 7,966 new WordPress ecosystem vulnerabilities in 2024, 96% of them in plugins and only seven in core, so plugin inventory and patch speed matter more than core settings.
  • Keep automatic updates on. WordPress minor and security releases install automatically by default, and the WordPress.org team can force critical plugin fixes; disabling the updater also blocks those pushes.
  • Treat stored keys as non-human identities. SMTP API keys, payment gateway secrets and application passwords live in wp_options or user meta, where a single information disclosure bug exposes all of them; patching does not revoke a key that has already leaked.
  • Remove the dashboard's ability to change code. DISALLOW_FILE_MODS, correct file ownership and no PHP execution in uploads turn a stolen admin session into a content problem rather than remote code execution.

PHP runtime: versions, configuration and PHP-FPM

The PHP project publishes support dates on its supported versions page. Each branch receives two years of active support followed by two years of security-only fixes. Running an end-of-life branch means no fix for the next PHP-level flaw, regardless of how well the application is written.

BranchReleasedActive support untilSecurity fixes untilStatus (October 2026)
8.520 Nov 202531 Dec 202731 Dec 2029Supported, preferred for new builds
8.421 Nov 202431 Dec 202631 Dec 2028Supported
8.323 Nov 202331 Dec 202531 Dec 2027Security fixes only
8.28 Dec 202231 Dec 202431 Dec 2026Security fixes only, plan migration now
8.1End of life 31 Dec 2025, last release 8.1.34Unsupported
8.0 and 7.4End of life 26 Nov 2023 and 28 Nov 2022Unsupported

Distributions sometimes backport fixes into older packaged branches, so check the distribution's own support statement too.

php.ini settings that reduce impact

The OWASP PHP Configuration Cheat Sheet gives a production baseline. The settings that matter most for real attacks:

  • expose_php = Off, display_errors = Off, log_errors = On: stop version banners and stack traces leaking paths, database names and query fragments to visitors, while keeping errors in a log you can read.
  • allow_url_include = Off and allow_url_fopen = Off: prevent a local file inclusion bug from turning into remote file inclusion. WordPress core and many plugins make outbound HTTP calls through the WordPress HTTP API, so test allow_url_fopen = Off before enforcing it.
  • open_basedir: confine file functions to the site's own directory tree, which limits what a path traversal or inclusion flaw can read, including other sites on the same server.
  • disable_functions: remove functions the application never uses, such as system, exec, shell_exec, passthru, popen and proc_open. This breaks most off-the-shelf web shells. Check plugin requirements first; backup and image plugins sometimes call exec.
  • Session cookies: session.cookie_httponly = 1, session.cookie_secure = 1, session.cookie_samesite = Strict (or Lax where cross-site navigation must keep sessions), session.use_strict_mode = 1 and session.use_only_cookies = 1 for custom PHP applications. WordPress uses its own authentication cookies rather than PHP sessions.
  • Uploads: set file_uploads = Off where an application accepts no uploads, and keep upload_max_filesize to what the business needs. See the File Upload Security Guide.

PHP-FPM and process isolation

  • One pool per site: give each site its own PHP-FPM pool running as its own Unix user. A compromise of one site then cannot write to another site's files, which is the most common way shared servers spread infections.
  • Code owned by a different user: the pool user should be able to write only to wp-content/uploads and any cache directory, not to PHP files in core, plugins or themes. Deploy code as a separate deployment user.
  • Avoid PHP-CGI on Windows: CVE-2024-4577, which CISA's KEV catalogue lists with known ransomware use, let attackers inject PHP-CGI arguments through Windows "Best-Fit" character conversion on certain code pages, bypassing the 2012 fix for CVE-2012-1823. The PHP advisory notes that default XAMPP installs were vulnerable; it was fixed in 8.3.8, 8.2.20 and 8.1.29. Use PHP-FPM or a supported module mode, and never expose php-cgi.exe.

WordPress core hardening

The WordPress Advanced Administration handbook sets the baseline. Most items are server settings that a plugin cannot provide.

ControlSetting or valueWhat it stops
File permissionsDirectories 755, files 644; wp-config.php 400 or 440; only wp-content (and uploads) writable by the web serverAttackers modifying core or plugin PHP after gaining code execution as the web server user
Dashboard code editingdefine( 'DISALLOW_FILE_EDIT', true ); or the stronger DISALLOW_FILE_MODS, which also blocks plugin and theme installs and updates from the dashboardA stolen administrator session writing a web shell through the theme editor or a malicious plugin upload
HTTPS for adminFORCE_SSL_ADMIN set to truePasswords and authentication cookies sent in the clear
Debug outputWP_DEBUG false in production; if WP_DEBUG_LOG is used, write the log outside the web root (the default is wp-content/debug.log, which is publicly reachable)Leaked paths, queries and occasionally credentials in a downloadable log
Database accountOne database and user per site; SELECT, INSERT, UPDATE and DELETE for normal running; no remote TCP access if not neededOne compromised site reading every other site's tables
Direct access to includesWeb server rules blocking wp-includes/*.php, wp-admin/includes and wp-config.phpDirect execution of include-only files
PHP in uploadsDeny PHP execution in wp-content/uploads at the web serverUploaded web shells (ATT&CK T1505.003) executing
Admin sign-inTwo-step authentication for every administrator and editor; optional server-level authentication in front of wp-admin (note it can break admin-ajax.php)Password spraying and credential stuffing
Integrity monitoringFile integrity checks on PHP files (OSSEC or similar), access and error logs retainedSilent persistence that survives a plugin update

Renaming the admin user, changing the wp_ table prefix and moving wp-config.php above the web root are secondary measures, no substitute for the controls above.

Plugins, themes and the WordPress vulnerability pattern

According to Patchstack's State of WordPress Security report covering 2024, 96% of the 7,966 new ecosystem vulnerabilities were in plugins and 4% in themes, cross-site scripting made up almost half, 43% needed no authentication, and 33% were not fixed by the time they were disclosed. These are vendor figures, but the pattern matches what CISA's KEV catalogue shows: exploited entries include the File Manager plugin (CVE-2020-25213, remote code execution), the Duplicator plugin (CVE-2020-11738, file download) and PHPMailer (CVE-2016-10033, command injection), a library many plugins bundle.

Core is not immune. In 2026 CISA added three WordPress core flaws to KEV: CVE-2026-60137 and CVE-2026-63030, which WordPress fixed in 7.0.2 (with backports to 6.9.5 and 6.8.6) and described as a REST API batch-route confusion and SQL injection issue that can lead to remote code execution, and CVE-2026-87902, a remote file inclusion through page-template resolution. For the 7.0.2 release WordPress.org forced the update through the automatic updater, so sites that support background updates started updating automatically, while sites with the updater disabled waited for a person to act.

  • Inventory first: list every plugin and theme per site with version, last update date and whether it is active. Inactive plugins still ship PHP files that can be requested directly, so delete rather than deactivate.
  • Source: install only from WordPress.org or vendors you can contact. Nulled (pirated) premium plugins are a common carrier of backdoors.
  • Abandonment: treat a plugin with no release for more than a year, or one closed on WordPress.org, as a removal candidate.
  • Risky functions: avoid plugins that execute PHP stored in the database or want write access to core files.
  • Developer code: custom REST routes must define a permission_callback (WordPress 5.5 and later emit a "doing it wrong" notice when it is missing), use validate_callback and sanitize_callback on arguments, and use prepared statements through $wpdb->prepare. PHP object injection through unserialize on user input remains a recurring plugin flaw; see the Insecure Deserialisation Guide.

Secrets in WordPress: wp-config, plugin settings and application passwords

A WordPress site holds more credentials than most teams realise, and almost all of them are long-lived. Each one is a non-human identity that needs an owner, a scope and a rotation plan. See the API Key Management Guide.

SecretWhere it usually livesBetter practice
Database credentials (DB_NAME, DB_USER, DB_PASSWORD, DB_HOST)wp-config.phpFile mode 400/440, outside version control; inject from environment variables or a secrets manager at deploy
Authentication keys and salts (AUTH_KEY, SECURE_AUTH_KEY, LOGGED_IN_KEY, NONCE_KEY and matching salts)wp-config.phpUnique per site; regenerate after a compromise, which invalidates every logged-in session
SMTP, transactional email and SMS API keyswp_options, written by pluginsDefine as constants or environment variables where the plugin allows; restrict provider keys to sending domains and rate limits
Payment, CRM and analytics API keyswp_optionsLeast-privilege keys from the provider; monitor provider-side usage
Application passwordsUser meta (hashed)One per integration, named, reviewed by last-used date and IP, revoked when the integration ends
Backups and exportswp-content or hosting storageEncrypt, store outside the web root, restrict access; a database dump contains every key above

The Gravity SMTP CVE-2026-4020 incident shows the failure mode. A plugin REST route under /wp-json/gravitysmtp/v1/ had a permission check that always allowed access, so unauthenticated requests could pull a system report containing the site's email provider API keys and SMTP passwords. Updating to 2.1.5 closed the route, but keys that had already been read stayed valid until each site owner rotated them at the provider.

Application passwords and the REST API

  • What they are: introduced in WordPress 5.6, application passwords authenticate REST API and (where enabled) XML-RPC requests with HTTP Basic authentication. They cannot be used to sign in through wp-login.php, and each can be revoked individually from the user profile or with WP-CLI by UUID.
  • Transport: they are available by default only over HTTPS, because Basic credentials are replayable if intercepted.
  • Scope: an application password carries the full capabilities of its user. Create a dedicated low-privilege user per integration (for example an Author for a publishing tool) rather than issuing one from an administrator account.
  • Disable where unused: the wp_is_application_passwords_available filter turns the feature off site-wide, and wp_is_application_passwords_available_for_user restricts it to specific users or roles, typically in a must-use plugin.
  • Browser requests: logged-in browser calls use cookie authentication plus a nonce created for the wp_rest action, sent in the X-WP-Nonce header. Do not install Basic Authentication plugins in production; the REST API handbook says they are for development only.
  • XML-RPC: if no client uses it, block xmlrpc.php at the web server or WAF; it accepts many credential attempts in one request. See the Web Application Firewall Guide.

Updates, Composer and dependency risk

WordPress automatic updates

  • Core: WP_AUTO_UPDATE_CORE accepts true (all), false (none) or 'minor' (maintenance and security releases only). Minor updates are on by default and new installations since 5.6 also receive major updates unless a version control checkout is detected.
  • Do not disable the updater: AUTOMATIC_UPDATER_DISABLED set to true turns off every automatic update, and the handbook strongly discourages disabling minor and translation updates. Returning __return_false from the auto_update_plugin filter also blocks the forced security pushes WordPress.org uses for critical plugin flaws.
  • Plugins and themes: enable auto-updates per plugin in the dashboard or with the auto_update_plugin filter for specific slugs. Sites with strict change control can disable them only if they deploy plugin updates through a pipeline within days, not weeks.
  • Version-controlled sites: if you set DISALLOW_FILE_MODS, the site can no longer update itself, so the deployment pipeline becomes the patch mechanism and must run on every security release. See the Patch Management Guide.

Composer for PHP applications and Composer-managed WordPress

  • composer audit: checks installed packages against the Packagist.org security advisories database (and other configured repositories), and also reports abandoned packages and packages flagged as malware. It exits with code 1 when anything matches, which makes it a usable CI gate.
  • Useful options: --locked audits composer.lock without a vendor directory, --no-dev skips development dependencies, --abandoned=fail fails the build on abandoned packages, and --format=json feeds results to a dashboard.
  • Lock and verify: commit composer.lock, install with composer install (never update) in CI, and pull private packages from a controlled repository to limit dependency confusion. See the Malicious Package and Dependency Confusion Guide.
  • Bundled libraries: plugins that ship their own copies of libraries such as PHPMailer are not seen by your composer audit. Vulnerability scanners that understand WordPress plugin versions cover that gap.

Choosing a hosting and operating model

ModelStrengthsTrade-offsFits
Managed WordPress hostingProvider handles PHP version, server hardening, often a WAF and malware scanningLess control over php.ini and pool isolation; plugin risk is still yoursSmall teams, marketing sites
Self-managed VM or container with dashboard updatesFull control of PHP-FPM, file ownership and loggingYou patch the OS and PHP; dashboard updates need web-server write access to plugin codeMid-sized organisations with a platform team
Immutable deploys (Composer-managed WordPress, read-only code, DISALLOW_FILE_MODS)Web server cannot write PHP; every change reviewed and reproduciblePatching depends entirely on the pipeline running promptlyLarge estates, regulated sites, agencies running many sites

Small organisations get the biggest gain from managed hosting with automatic updates for core and plugins, two-step sign-in for every administrator and a short plugin list. Large estates should standardise on an immutable build, central plugin approval and one view of versions across all sites. Agencies holding administrator access to many client sites are a concentrated credential target.

Implementation roadmap

  1. Inventory (week 1): list every PHP application and WordPress site, PHP branch, core version, plugins, themes, administrators and stored integration keys. Flag anything on PHP 8.1 or earlier.
  2. Quick wins (week 1 to 2): enforce two-step sign-in for administrators, remove unused plugins and administrator accounts, confirm minor auto-updates are on, set DISALLOW_FILE_EDIT and FORCE_SSL_ADMIN, and switch WP_DEBUG off.
  3. Server hardening (weeks 2 to 4): fix file ownership, deny PHP in uploads, split PHP-FPM pools per site, apply the php.ini baseline. Test on staging first, and roll back by restoring the previous pool and ini files if a plugin fails; keep the old configuration in version control.
  4. Secrets (weeks 3 to 6): rotate database passwords and salts on any site with an unknown history, move integration keys into constants or environment variables where plugins support it, scope provider keys, and review application passwords by last-used date.
  5. Runtime upgrade (by Q4 2026): move every site off PHP 8.2 before its security support ends on 31 December 2026. Run the site on the target branch in staging with error logging on, fix deprecations, then cut over with the previous pool kept available for a fast switch back.
  6. Pipeline (ongoing): add composer audit and a WordPress-aware vulnerability scan to CI, and alert on KEV-listed WordPress, PHP and plugin CVEs within 24 hours.

Detection and measurement

  • Web logs: requests to PHP files under wp-content/uploads, POSTs to xmlrpc.php, bursts of failed wp-login.php attempts, unauthenticated calls to /wp-json/ plugin routes returning large bodies, and requests carrying %ad sequences on Windows PHP hosts.
  • File integrity: new or changed .php files outside a planned deployment, compared with WordPress core checksums (WP-CLI wp core verify-checksums).
  • WordPress events: new administrator accounts, role changes, new application passwords, plugin installs and option changes to siteurl or active_plugins.
  • Provider side: unexpected sending volume or new source IPs on email and payment API keys, which is often the first sign a key leaked.
MetricTarget
Sites on a supported PHP branch100%, with none on a branch inside six months of end of life
Median time from plugin security release to deploymentUnder 72 hours; under 24 hours for KEV-listed or actively exploited flaws
Administrator accounts with two-step sign-in100%
Installed but inactive pluginsZero
Application passwords unused for 90 daysZero (revoked)
Composer builds with open high or critical advisoriesZero merged to production

Common failure patterns

  • Patching without rotating: a plugin information disclosure is fixed but the keys it exposed are never rotated, as in the Gravity SMTP CVE-2026-4020 incident, where mass scanners collected email provider keys and abuse continued after the update.
  • Turning off the updater for stability: AUTOMATIC_UPDATER_DISABLED or a blanket auto_update_plugin false filter stops the forced security pushes that protected other sites during the 2026 core SQL injection fixes.
  • Deactivated, not deleted: vulnerable plugin files remain reachable by direct request long after the plugin was "turned off".
  • Web server owns the code: when the PHP user can write to plugins and themes, any upload or inclusion flaw becomes a persistent web shell.
  • Administrator-backed integrations: an application password or API connector issued from an administrator account gives every integration full control of the site.
  • Old PHP on forgotten sites: staging copies, microsites and agency-built campaign sites left on end-of-life PHP with outdated plugins and live production database credentials.

Framework mapping

AreaNIST SP 800-53 Rev. 5NIST CSF 2.0MITRE ATT&CK
PHP, core and plugin patchingSI-2 Flaw Remediation, RA-5ID.RA-01, PR.PS-02T1190 Exploit Public-Facing Application
php.ini, file permissions, disabled editorsCM-6 Configuration Settings, CM-7 Least FunctionalityPR.PS-01T1505.003 Web Shell
Keys, salts and application passwordsIA-5 Authenticator Management, AC-6PR.AA-01, PR.AA-05T1552.001 Credentials In Files
Composer and plugin supply chainSR-3, SA-11ID.RA-01T1195.002 Compromise Software Supply Chain
Logging and file integrityAU-2 Event LoggingDE.CM-09T1505.003 Web Shell

In ISO/IEC 27001:2022 Annex A the same work falls mainly under A.8.8 (management of technical vulnerabilities), A.8.9 (configuration management) and A.8.28 (secure coding), and in CIS Controls v8.1 under Control 7 (continuous vulnerability management) and Control 16 (application software security). See the Secure Coding Guide and the CWE Top 25 Guide.

Practitioner checklist

  • Every site runs PHP 8.3 or later, or has a dated plan to leave 8.2 before 31 December 2026.
  • php.ini sets expose_php and display_errors off, allow_url_include off, open_basedir and a disable_functions list tested against your plugins.
  • Each site has its own PHP-FPM pool user, and that user cannot write PHP files.
  • wp-config.php is mode 400 or 440, unique salts are set, DISALLOW_FILE_EDIT (or DISALLOW_FILE_MODS) and FORCE_SSL_ADMIN are true, WP_DEBUG is false.
  • PHP execution is denied in wp-content/uploads and xmlrpc.php is blocked if unused.
  • Core minor auto-updates are on and the updater is not disabled; plugin updates are automatic or pipeline-deployed within 72 hours.
  • Unused plugins and themes are deleted, and every remaining plugin has a named owner.
  • Integration keys are scoped at the provider and rotated after any plugin disclosure flaw; application passwords belong to dedicated low-privilege users.
  • composer audit runs in CI with --locked and fails the build on high or critical advisories.
  • File integrity monitoring and alerts on new administrators and new application passwords feed the SOC.

Standards and references

Related NHI Mgmt Group resources: Insecure Deserialisation Guide · File Upload Security Guide · Web Application Firewall Guide · Secure Coding Guide · Secrets Management Guide

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Written and reviewed by Lalit Choda, NHI Mgmt Group. Last updated 24 October 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.