wp_sanitize_redirect strips out @ signs (even from parameters) — why?

In my WordPress site I have a hack that looks at the uri and does a redirect to a subdomain. The problem is wp_redirect calls wp_sanitize_redirect which will strip out @ signs, so when a user tries to load something like

oursite.com?email=foo@bar.com

The page that gets loaded should be

Read More
prefix.oursite.com?email=foo@bar.com

but instead it’s

prefix.oursite.com?email=foobar.com (i.e. - no @ sign)

The problem is easy to work around – I just manually encode @ signs as %40 before calling wp_redirect.

Question: why does wp_sanitize_redirect strip out @ signs, exactly? Anybody could anyway try to load a url with an @ sign in it – is there some security issue I’m not thinking about?

EDIT: The function I’m talking about is wp_sanitize_redirect

Related posts

Leave a Reply

2 comments

  1. Question why does wp_sanitize_redirect strip out @ signs, exactly? Anybody could anyway try to load a url with an @ sign in it – is there some security issue I’m not thinking about?

    Just take a look at the source:

    function wp_sanitize_redirect($location) {
        $location = preg_replace('|[^a-z0-9-~+_.?#=&;,/:%!]|i', '', $location);
        $location = wp_kses_no_null($location);
    
        // remove %0d and %0a from location
        $strip = array('%0d', '%0a', '%0D', '%0A');
        $location = _deep_replace($strip, $location);
        return $location;
    }
    

    So the only characters, the preg_replace allows are

    • lower case a-z
    • numbers
    • and ~+_.?#=&;,/:%!.

    What does that mean for URIs and URLs?

    The php function urlencode() replaces all no alpha-numeric chararcters, except -_. with a % (percent) character followed by two hexdecimal values and spaces with a +. If you use rawurlencode(), it also strips the +. As you can see from the preg_replace(), it allows all URL encoded/prepared characters, so it’s safe to throw such encoded characters/URL parts into the game.

  2. Just wanted to follow up on my own findings. This happened to me if I was leaving out the last / in my URLs. Doing so caused WP to call func:redirect_canonical which stripped out the @ symbols. When I added the last / it did not call this function and the @ symbol remained.

    A good plugin for debugging redirects is: Debug WP Redirect

    Example 1 which fails:

    Original URL: http://www.domain.com/somepage?email=me@me.com

    Final URL : http://www.domain.com/somepage/?email=meme.com

    Example 2 which works:

    Original URL: http://www.domain.com/somepage/?email=me@me.com

    Final URL : http://www.domain.com/somepage/?email=me@me.com