Title: Security Hardener
Author: Marc Armengou
Published: <strong>3 de Noviembre de  2025</strong>
Last modified: 2 de Abril de  2026

---

Buscar plugins

![](https://ps.w.org/security-hardener/assets/icon-256x256.png?rev=3389141)

# Security Hardener

 Por [Marc Armengou](https://profiles.wordpress.org/marc4/)

[Descargar](https://downloads.wordpress.org/plugin/security-hardener.2.2.0.zip)

[Vista previa](https://cl.wordpress.org/plugins/security-hardener/?preview=1)

 * [Detalles](https://cl.wordpress.org/plugins/security-hardener/#description)
 * [Reseñas](https://cl.wordpress.org/plugins/security-hardener/#reviews)
 *  [Instalación](https://cl.wordpress.org/plugins/security-hardener/#installation)
 * [Desarrollo](https://cl.wordpress.org/plugins/security-hardener/#developers)

 [Soporte](https://wordpress.org/support/plugin/security-hardener/)

## Descripción

**Security Hardener** applies WordPress security best practices based on the [WordPress Advanced Administration / Security / Hardening](https://developer.wordpress.org/advanced-administration/security/hardening/)
documentation and widely accepted hardening measures. It uses WordPress core functions
and follows best practices without modifying core files.

#### Key Features

**File Security:**
 * Disable file editor in WordPress admin * Optionally disable
all file modifications (blocks updates – use with caution)

**XML-RPC Protection:**
 * Disable XML-RPC completely (enabled by default) * Remove
pingback methods when XML-RPC is enabled

**Pingback Protection:**
 * Disable self-pingbacks * Remove X-Pingback header * 
Block incoming pingbacks

**User Enumeration Protection:**
 * Block `/?author=N` queries (returns 404) * Secure
REST API user endpoints (require authentication) * Remove users from XML sitemaps*
Prevent canonical redirects that expose usernames * Optionally block author feed
pages (`/author/username/feed/`)

**Login Security:**
 * Generic error messages (no username/password hints) * Login
honeypot — silently blocks bots before any credential check * IP-based rate limiting
with configurable thresholds * Security event logging (last 100 events) * Automatic
blocking after failed attempts

**Security Headers:**
 * `X-Frame-Options: SAMEORIGIN` (clickjacking protection)*`
X-Content-Type-Options: nosniff` (MIME sniffing protection) * `Referrer-Policy: 
strict-origin-when-cross-origin` * `Permissions-Policy` (restricts geolocation, 
microphone, camera) * Optional HSTS (HTTP Strict Transport Security) for HTTPS sites—
max-age set to 1 year

**Additional Hardening:**
 * Hide WordPress version (meta generator tag and asset
query strings) * Remove obsolete wp_head items (RSD, WLW manifest, shortlink, emoji
scripts) * Security event logging system * Optionally disable Application Passwords
for API authentication

> ⚠️ **Important:** Always test security settings in a staging environment first.
> Some features may affect third-party integrations or plugins.

**Privacy:** This plugin does not send data to external services and does not create
custom database tables. It stores plugin settings and a security event log in the
WordPress options table, and uses transients for temporary login attempt tracking.
All data is preserved on uninstall by default and only deleted if the “Delete all
data on uninstall” option is explicitly enabled.

## Instalación

#### Automatic Installation

 1. Go to **Plugins > Add New Plugin**
 2. Search for **Security Hardener**
 3. Click **Install Now** and then **Activate**
 4. Configure settings at **Settings > Security Hardener**

## FAQ

### What are the default settings?

By default, the plugin enables:
 * File editor disabled * XML-RPC disabled * User
enumeration blocking * Generic login errors * Login honeypot * Login rate limiting(
5 attempts per 15 minutes) * Security headers * WordPress version hiding (meta generator
tag and asset query strings) * Clean wp_head output * Security event logging

HSTS and author feed blocking are disabled by default. Disabling Application Passwords
is also disabled by default — only enable it if you are sure no integrations or 
third-party apps use REST API authentication.

### Does this plugin slow down my site?

No. The plugin uses lightweight WordPress hooks and native functions. Security headers
add negligible overhead, and rate limiting only checks transients during login attempts.

### I use a CDN or proxy (Cloudflare, etc.). How do I get the correct IP?

By default, rate limiting uses `REMOTE_ADDR`. If behind a trusted proxy, add this
to `wp-config.php`:

    ```
    define('WPSH_TRUSTED_PROXIES', array(
        '173.245.48.0',  // Example: Cloudflare IP range
        // Add your proxy IPs here
    ));
    ```

The plugin will then check `HTTP_CF_CONNECTING_IP` (Cloudflare) or `HTTP_X_FORWARDED_FOR`
headers.

### What headers does this plugin add?

When security headers are enabled:
 * `X-Frame-Options: SAMEORIGIN` * `X-Content-
Type-Options: nosniff` * `Referrer-Policy: strict-origin-when-cross-origin` * `Permissions-
Policy: geolocation=(), microphone=(), camera=()`

When HSTS is enabled (HTTPS only):
 * `Strict-Transport-Security: max-age=31536000`(
optionally with `includeSubDomains` if enabled)

### Does the plugin work with page caching?

Yes. Security headers are sent at the PHP level before caching. However, if you 
use aggressive server-level caching, you may need to configure your cache to allow
these headers through.

### Can I use this with other security plugins?

Yes, but be careful of conflicts. If another plugin also:
 * Sends security headers,
you may get duplicates (usually harmless) * Blocks user enumeration, one should 
be disabled * Has login rate limiting, choose one to avoid confusion

This plugin is designed to be lightweight and focused on core WordPress hardening.

### What happens to my data when I uninstall?

When you **uninstall** (not just deactivate) the plugin, data is preserved by default.
If you have enabled the **“Delete all data on uninstall”** option under Settings
> Security Hardener > Other Settings, then on uninstall:
 * All plugin settings 
are deleted * All security logs are deleted * All login rate limiting transients
are cleared * Your WordPress installation is returned to its default state

**Note:** Deactivating the plugin always preserves all settings.

### Does this block the WordPress REST API?

No. The plugin only secures user-related endpoints by requiring authentication. 
All other REST API functionality works normally. Public endpoints like oEmbed continue
to work.

### I’m locked out after too many failed attempts. What do I do?

Failed login blocks expire automatically based on your configured window (default:
15 minutes). Wait for the block period to expire, or:

 1. Access your database (phpMyAdmin, etc.)
 2. Search for options with `_transient_wpsh_login_` in the name
 3. Delete those transient options
 4. Try logging in again

### How do I know if the plugin is working?

 1. Check **Settings > Security Hardener** for active features
 2. Review the “Recent Security Events” log
 3. Use browser dev tools to inspect HTTP headers
 4. Try accessing `/?author=1` (should return 404 if blocking is enabled)
 5. Test failed login attempts to verify rate limiting

### Does this plugin require HTTPS?

Not required, but **strongly recommended**. HSTS features require HTTPS. For maximum
security, your entire site should use HTTPS with a valid SSL certificate.

### Is this plugin compatible with multisite?

The plugin is designed for single-site installations. Multisite compatibility has
not been tested and is not officially supported at this time.

## Reseñas

No hay reseñas para este plugin.

## Colaboradores & Desarrolladores

“Security Hardener” es software de código abierto. Las siguientes personas han contribuido
a este plugin.

Colaboradores

 *   [ Marc Armengou ](https://profiles.wordpress.org/marc4/)

“Security Hardener” ha sido traducido en 3 idiomas. Gracias a [los traductores](https://translate.wordpress.org/projects/wp-plugins/security-hardener/contributors)
por sus contribuciones.

[Traduce “Security Hardener” a tu idioma.](https://translate.wordpress.org/projects/wp-plugins/security-hardener)

### ¿Interesado en el desarrollo?

[Revisa el código](https://plugins.trac.wordpress.org/browser/security-hardener/),
echa un vistazo al [repositorio SVN](https://plugins.svn.wordpress.org/security-hardener/),
o suscríbete al [registro de desarrollo](https://plugins.trac.wordpress.org/log/security-hardener/)
por [RSS](https://plugins.trac.wordpress.org/log/security-hardener/?limit=100&mode=stop_on_copy&format=rss).

## Historial de cambios

#### 2.2.0 – 2026-04-01

 * Added: Login honeypot — a hidden field added to the login form that silently 
   blocks bots before any credential check.
 * Added: Block author feeds — optionally blocks /author/username/feed/ pages that
   can confirm existing usernames.
 * Added: Disable Application Passwords — disables REST API authentication via Application
   Passwords; enabled by default.
 * Added: System Status section — replaces the separate File Permissions section;
   shows file permissions and WP_DEBUG status in a unified table, always visible
   with with color-coded indicators.
 * Added: Two new items to the hardening checklist — disable display_errors in PHP
   configuration, and disable WP_DEBUG_DISPLAY on live sites.

#### 2.1.1 – 2026-03-29

 * Improved: Interactive elements (toggles, checklist, progress bar) now use WordPress
   admin theme color variables.
 * Fixed: “Settings saved.” notice no longer appears twice after saving settings.
 * Fixed: Checklist progress counter now stays translated when updated via AJAX.
 * Fixed: Removed orphan comment from show_admin_notices().
 * Fixed: Removed dead CSS for .wpsh-recommendations.

#### 2.1.0 – 2026-03-26

 * Added: Interactive hardening checklist — users can mark each recommendation as
   done.
 * Improved: File permissions check moved from floating admin notice into the settings
   page.
 * Fixed: “Enable preload” description now clarifies it only adds the preload directive
   to the HSTS header.
 * Fixed: “Clean wp_head” description no longer uses HTML entities that rendered
   as literal text in some contexts.
 * Fixed: wp-includes recommendation text no longer implies a code snippet follows.

#### 2.0.2 – 2026-03-21

 * Improved: Number fields now show allowed range as permanent help text (Min/Max)
   below the label.
 * Fixed: Lost password flow now uses lostpassword_errors filter instead of login_messages.
 * Fixed: “Clear Logs” replaced JavaScript confirm() with a proper POST form.
 * Fixed: $_POST[‘wpsh_action’] sanitized with sanitize_key() before comparison,
   following WordPress Coding Standards.

#### 2.0.1 – 2026-03-21

 * Fixed: “Block user enumeration” description now mentions canonical redirect blocking
 * Fixed: “Login rate limiting” toggle and number fields now have descriptions for
   consistency with all other options
 * Fixed: Removed unused WPSH_DIR and WPSH_URL constants
 * Fixed: Removed misleading inline comment about file editing in init()
 * Fixed: readme — “Disable self-pingbacks” moved from XML-RPC section to its own
   Pingback Protection section
 * Fixed: Unused parameters in clear_login_attempts() prefixed with underscore following
   WordPress Coding Standards
 * Fixed: @return docblock for get_default_options() updated to array<string, int
   > for accuracy
 * Fixed: Activation and deactivation log messages now pass through __() for translation
 * Fixed: remove_login_hints() no longer relies on hardcoded English string comparison
 * Fixed: strpos() replaced with str_starts_with() in disable_self_pingbacks() —
   consistent with PHP 8.2+ usage throughout the plugin
 * Fixed: Explicit string types added to log_security_event() method signature
 * Fixed: @param docblock of clear_login_attempts() updated to reflect renamed parameters
   $_user_login and $_user

#### 2.0.0 – 2026-03-20

 * Improved: Complete redesign of the settings page — responsive 3-column card grid
   replaces the default WordPress Settings API table layout
 * Improved: Checkboxes replaced with CSS toggles for clearer on/off state at a 
   glance
 * Improved: “Clear Logs” button moved inline next to the section heading
 * Improved: Minimal inline CSS scoped to .wpsh-* classes — no external stylesheet
   enqueued
 * Removed: “Enable security headers” master toggle — each header is now controlled
   individually
 * Removed: Configurable HSTS max-age field — hardcoded to 31536000 seconds (1 year),
   the universally recommended value
 * Fixed: HSTS “Include subdomains” now defaults to disabled — users must opt in
   explicitly
 * Improved: “Hide WordPress version” now also strips the WordPress version from
   script and style asset URLs (?ver=), preventing version detection via asset URLs
 * Improved: “Hide WordPress version” moved from “User Enumeration” to “Other Settings”
 * Improved: “Clean wp_head” no longer removes feed links extra — avoids conflicts
   with plugins that rely on category and tag feeds
 * Improved: “Clean wp_head” no longer removes wp_generator — already covered by“
   Hide WordPress version”
 * Improved: All toggle descriptions updated for consistency — each option now explains
   what value or behaviour it applies
 * Added: New “Additional Hardening Recommendations” section in the plugin admin
   page and readme, including four measures from the official WordPress Hardening
   Guide not previously listed: rename admin account, restrict database user privileges,
   protect wp-config.php, and block direct access to wp-includes/

#### 1.0 – 2026-03-05

 * Updated: Minimum WordPress requirement raised to 6.9
 * Updated: Minimum PHP requirement raised to 8.2
 * Improved: Applied PHP 8.3 modern syntax throughout — typed class properties, 
   explicit return types on all methods, short array syntax, and `match` expression
   in `sanitize_options()`
 * Added: `delete_data_on_uninstall` option (default: disabled) — users must explicitly
   opt in to data deletion on uninstall; data is preserved by default
 * Fixed: `uninstall.php` no longer uses direct SQL queries; deletion is now conditional
   on the opt-in option and uses WordPress APIs exclusively
 * Fixed: `WPSH_VERSION` constant kept in sync with plugin header at `1.0`

#### 0.8 – 2026-02-26

 * Improved: Moved define_security_constants() from plugins_loaded hook to the constructor,
   ensuring DISALLOW_FILE_EDIT and DISALLOW_FILE_MODS are defined as early as possible
   in the WordPress lifecycle
 * Improved: Expanded @param docblock for render_checkbox_field() to document all
   $args keys
 * Added: WordPress Playground blueprint (assets/blueprints/blueprint.json) enabling
   live plugin preview directly from the WordPress.org plugin directory
 * Fixed: Plugin header description updated to remove REST API restriction option
   removed in 0.5
 * Fixed: Removed stale phpcs:ignore comment in show_admin_notices() — nonce verification
   is now correctly documented inline
 * Fixed: Wrapped login block error message with wp_kses_post() for consistent output
   escaping
 * Fixed: Added esc_url() and esc_html__() to add_settings_link() sprintf output
 * Fixed: Removed redundant get_client_ip() call in log_security_event() — IP resolved
   once per event
 * Fixed: Added autoload=false to wpsh_security_logs option — logs are only needed
   on the settings page, not loaded on every request

#### 0.7 – 2026-02-21

 * Fixed: WPSH_VERSION constant updated to match plugin header version
 * Fixed: Added wp_unslash() and sanitize_text_field() to $_GET[‘author’] in prevent_author_redirect()
 * Fixed: Moved HTML markup outside translatable strings in generic_login_errors(),
   check_login_rate_limit(), and field descriptions for “Disable all file modifications”
   and “Enable HSTS”
 * Security: Added CSRF protection to “Clear Logs” action via wp_nonce_url() and
   wp_verify_nonce()
 * Improved: Added missing hardening recommendations to admin page: BasicAuth protection
   for wp-admin and changing the default database table prefix
 * Fixed: Corrected date format in changelog entries (YYYY-MM-DD)

#### 0.6 – 2026-02-21

 * Fixed: Removed deprecated load_plugin_textdomain() call (automatic since WordPress
   4.6)
 * Fixed: Added wp_unslash() and sanitize_text_field() to $_GET[‘author’] before
   sanitization
 * Fixed: Moved HTML markup outside translatable string in login confirmation message
 * Fixed: Escaped $min and $max output in render_number_field() using absint()
 * Fixed: Added phpcs:ignore for native WordPress constants DISALLOW_FILE_EDIT and
   DISALLOW_FILE_MODS
 * Fixed: Removed error_log() debug call from uninstall.php
 * Fixed: Suppressed false-positive direct database query warning in uninstall.php
   with inline justification comment
 * Fixed: Removed redundant function_exists() check for wp_cache_flush() in uninstall.
   php

#### 0.5 – 2026-02-09

 * Complete rewrite following WordPress hardening best practices
 * Increased minimum PHP requirement to 8.0 (PHP 7.4 is end-of-life)
 * Added: Security event logging system (last 100 events)
 * Added: File permission checking with admin notices
 * Improved: User enumeration blocking (now also blocks REST endpoints and sitemaps)
 * Improved: Rate limiting algorithm (more reliable, fewer race conditions)
 * Improved: IP detection with proper proxy support via `WPSH_TRUSTED_PROXIES` constant
 * Improved: Admin interface with better organization and descriptions
 * Improved: Code quality following WordPress Coding Standards
 * Removed: CSP (Content Security Policy) – requires per-site customization
 * Removed: REST API restriction option – too broad, better handled per-case
 * Fixed: All security vulnerabilities from previous versions
 * Fixed: Proper sanitization and escaping throughout

#### 0.3 – 2025-10-20

 * Some corrections

#### 0.2 – 2025-10-13

 * Some corrections

#### 0.1 – 2025-10-04

 * Initial release

## Meta

 *  Versión **2.2.0**
 *  Última actualización **hace 6 días**
 *  Instalaciones activas **100+**
 *  Versión de WordPress ** 6.9 o superior **
 *  Probado hasta **6.9.4**
 *  Versión de PHP ** 8.2 o superior **
 *  Idiomas
 * [Catalan](https://ca.wordpress.org/plugins/security-hardener/), [English (US)](https://wordpress.org/plugins/security-hardener/),
   [Spanish (Chile)](https://cl.wordpress.org/plugins/security-hardener/), y [Spanish (Spain)](https://es.wordpress.org/plugins/security-hardener/).
 *  [Traducir a tu idioma](https://translate.wordpress.org/projects/wp-plugins/security-hardener)
 * Etiquetas
 * [Brute Force](https://cl.wordpress.org/plugins/tags/brute-force/)[hardening](https://cl.wordpress.org/plugins/tags/hardening/)
   [headers](https://cl.wordpress.org/plugins/tags/headers/)[login protection](https://cl.wordpress.org/plugins/tags/login-protection/)
   [security](https://cl.wordpress.org/plugins/tags/security/)
 *  [Vista Avanzada](https://cl.wordpress.org/plugins/security-hardener/advanced/)

## Calificaciones

Aún no se han enviado valoraciones.

[Your review](https://wordpress.org/support/plugin/security-hardener/reviews/#new-post)

[Ver todas las reseñas](https://wordpress.org/support/plugin/security-hardener/reviews/)

## Colaboradores

 *   [ Marc Armengou ](https://profiles.wordpress.org/marc4/)

## Soporte

¿Tienes algo que decir? ¿Necesitas ayuda?

 [Ver el foro de soporte](https://wordpress.org/support/plugin/security-hardener/)