Gene Library Courses Download Pricing Contact Sign in
GENE-WPPLUGINSBUILDER Development Best Practices

Using wp_safe_redirect() for Secure WordPress Redirect Handling

Overview

Redirects are a common part of WordPress plugin and theme functionality.

Plugins may redirect users after:

  • Form submissions.
  • Login actions.
  • Settings updates.
  • Payment flows.
  • Administrative actions.

However, redirects that rely on user-controlled URLs can introduce security risks.

The main concern is an open redirect vulnerability, where attackers manipulate redirect destinations to send users to malicious websites.

WordPress provides two commonly used redirect functions:

  • wp_redirect()
  • wp_safe_redirect()

For most plugin and theme redirects, wp_safe_redirect() is the recommended choice.

Understanding the Risk of wp_redirect()

The wp_redirect() function performs a redirect but does not automatically verify whether the destination URL is safe.

If a redirect destination is controlled by user input, an attacker may modify the URL.

Example of a risky pattern:

$url = $_GET['redirect'];

wp_redirect( $url );
exit;

An attacker could provide a malicious destination and cause users to leave the trusted website.

Potential consequences include:

  • Phishing attacks.
  • Fake login pages.
  • Social engineering attempts.
  • Malware distribution.

The problem is not the redirect itself. The problem is allowing untrusted input to control where users are sent.

How wp_safe_redirect() Improves Security

wp_safe_redirect() adds an additional security layer by validating the redirect destination.

It checks whether the destination is:

  • A local URL.
  • A trusted host.
  • An explicitly allowed external destination.

If the destination is not considered safe, WordPress falls back to a safe location.

Example:

wp_safe_redirect( $url );
exit;

This prevents attackers from easily redirecting users to arbitrary external websites.

Default to Safe Redirects

As a general development practice:

Use wp_safe_redirect() unless you have a specific reason to use wp_redirect().

Most WordPress plugin redirects are internal, meaning users are being sent to another page on the same website.

Examples include:

  • Redirecting after saving plugin settings.
  • Returning users to a dashboard page.
  • Sending users back after submitting a form.

These cases should normally use wp_safe_redirect().

Always Stop Execution After Redirects

Redirect functions send HTTP headers, but they do not automatically stop PHP execution.

Use exit or wp_die() after performing a redirect.

Example:

wp_safe_redirect( admin_url( 'options-general.php' ) );
exit;

This prevents additional code from running after the redirect response has been sent.

Handling External Redirects Safely

Some plugins may legitimately need to redirect users to another website.

Examples:

  • Sending users to a payment provider.
  • Linking to an external service.
  • Opening a partner platform.

In these cases:

  • Prefer hardcoded URLs.
  • Avoid accepting arbitrary external URLs from users.
  • Validate destinations carefully.

Example:

Safe:

wp_safe_redirect( 'https://example.com/account' );
exit;

Risky:

wp_safe_redirect( $_GET['external_url'] );
exit;

User-controlled external redirects should never be trusted without validation.

Allowing Specific External Hosts

In some situations, dynamic external redirects are required.

WordPress provides the allowed_redirect_hosts filter to explicitly approve trusted domains.

This allows developers to maintain security while supporting controlled external destinations.

A whitelist approach is safer because only approved domains are permitted.

Avoid allowing all external hosts, as this removes the security benefit of validation.

Common Redirect Mistakes

Trusting User Input Directly

Incorrect:

wp_redirect( $_GET['url'] );
exit;

The user controls the destination.

Better:

wp_safe_redirect( home_url( '/dashboard/' ) );
exit;

The destination is controlled by the application.

Forgetting to Exit

Incorrect:

wp_safe_redirect( home_url() );

Correct:

wp_safe_redirect( home_url() );
exit;

Stopping execution ensures no additional processing happens after the redirect.

Redirect Security Checklist

Before releasing a plugin, confirm that:

  • Local redirects use wp_safe_redirect().
  • User-provided URLs are not trusted automatically.
  • External destinations are controlled or validated.
  • Redirect execution is stopped afterward.
  • Allowed external hosts are explicitly limited.
  • Open redirect vulnerabilities have been considered.

Summary

Secure redirect handling is an important part of WordPress plugin development.

Developers should:

  • Prefer wp_safe_redirect() for normal redirects.
  • Avoid sending users to arbitrary user-controlled URLs.
  • Validate external destinations.
  • Use allowlists for approved external hosts.
  • Stop execution after redirects.

Using safe redirect practices protects users from phishing attempts, malicious redirects, and other security risks while keeping plugin navigation reliable.

Frequently Asked Questions

Why should I use wp_safe_redirect() instead of wp_redirect()?
wp_safe_redirect() performs additional validation to reduce the risk of open redirect vulnerabilities. It checks whether the destination is a trusted local URL or an approved host before redirecting.
What is an open redirect vulnerability?
An open redirect vulnerability occurs when a website redirects users to a URL controlled by an attacker. This can be used for phishing, social engineering, or directing users to malicious websites.
Does wp_redirect() always create a security vulnerability?
No. wp_redirect() is not inherently unsafe, but it becomes risky when the redirect destination comes from user-controlled input without proper validation.
Can wp_safe_redirect() redirect users to external websites?
Yes, but external hosts must be explicitly trusted. Developers should avoid dynamic external redirects unless the destination is controlled through a safe allowlist.
What should I do if my plugin requires redirects to external domains?
Use hardcoded external URLs whenever possible. If dynamic external redirects are required, use the allowed_redirect_hosts filter to explicitly allow trusted domains.